From df6e6f5635bd6dba1c7ab4c59019f735f29ec88c Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Mon, 5 Nov 2018 13:07:20 +0100 Subject: [PATCH 001/119] 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 e4dc5f3d93b911ad259a2352ddebc0c013132921 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Wed, 14 Nov 2018 18:47:17 +0200 Subject: [PATCH 002/119] Update open zeppelin and oraclize (#398) * Updated oraclizeAPI to version 0.4.25 * Updated: imports, use owner() * Fixed compilation errors (transfer in ReclaimTokens commented) * IERC20 instead of IERC20Extended * fix for "truffle test" * reverted changes in PolyToken * fixed creation of SecurityToken in tests * fix tests * fixed SecurityToken._burn * Removed redundant checking. * fix merge * Removed redundant checking. * Coverage Fixed * Updated yarn.lock * Some function name changes to avoid namespace clashes with OZ --- contracts/ModuleRegistry.sol | 2 +- contracts/ReclaimTokens.sol | 4 +- contracts/SecurityTokenRegistry.sol | 2 +- contracts/external/oraclizeAPI.sol | 33 ++- contracts/helpers/PolyToken.sol | 4 +- .../interfaces/{IERC20.sol => IPoly.sol} | 2 +- contracts/mocks/MockBurnFactory.sol | 2 +- .../modules/Checkpoint/DividendCheckpoint.sol | 2 +- .../Checkpoint/ERC20DividendCheckpoint.sol | 2 +- .../ERC20DividendCheckpointFactory.sol | 2 +- .../EtherDividendCheckpointFactory.sol | 2 +- .../Burn/TrackedRedemptionFactory.sol | 2 +- .../Mixed/ScheduledCheckpointFactory.sol | 2 +- .../LockupVolumeRestrictionTMFactory.sol | 2 +- .../SingleTradeVolumeRestrictionTMFactory.sol | 2 +- contracts/modules/Module.sol | 2 +- contracts/modules/ModuleFactory.sol | 2 +- .../GeneralPermissionManagerFactory.sol | 2 +- contracts/modules/STO/CappedSTO.sol | 2 +- contracts/modules/STO/CappedSTOFactory.sol | 2 +- contracts/modules/STO/DummySTOFactory.sol | 2 +- contracts/modules/STO/ISTO.sol | 2 +- contracts/modules/STO/PreSaleSTOFactory.sol | 2 +- contracts/modules/STO/USDTieredSTO.sol | 7 +- contracts/modules/STO/USDTieredSTOFactory.sol | 2 +- .../CountTransferManagerFactory.sol | 2 +- .../GeneralTransferManagerFactory.sol | 2 +- .../ManualApprovalTransferManagerFactory.sol | 2 +- .../PercentageTransferManagerFactory.sol | 2 +- contracts/oracles/PolyOracle.sol | 2 +- contracts/proxy/UpgradeabilityProxy.sol | 4 +- contracts/tokens/SecurityToken.sol | 56 +++-- package.json | 2 +- test/b_capped_sto.js | 8 +- test/c_checkpoints.js | 4 +- test/d_count_transfer_manager.js | 4 +- test/e_erc20_dividends.js | 4 +- test/f_ether_dividends.js | 4 +- test/g_general_permission_manager.js | 4 +- test/h_general_transfer_manager.js | 4 +- test/helpers/contracts/PolyToken.sol | 4 +- test/i_Issuance.js | 4 +- test/j_manual_approval_transfer_manager.js | 4 +- test/k_module_registry.js | 8 +- test/l_percentage_transfer_manager.js | 4 +- test/m_presale_sto.js | 4 +- test/n_security_token_registry.js | 10 +- test/o_security_token.js | 36 ++-- test/p_usd_tiered_sto.js | 4 +- test/q_usd_tiered_sto_sim.js | 4 +- test/r_concurrent_STO.js | 4 +- test/s_v130_to_v140_upgrade.js | 8 +- test/t_security_token_registry_proxy.js | 4 +- test/v_tracked_redemptions.js | 4 +- ...kup_volume_restriction_transfer_manager.js | 4 +- test/x_single_trade_volume_restriction.js | 4 +- test/y_scheduled_checkpoints.js | 4 +- yarn.lock | 203 +++++++++--------- 58 files changed, 268 insertions(+), 243 deletions(-) rename contracts/interfaces/{IERC20.sol => IPoly.sol} (98%) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index b2f1fbba5..e376a8301 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -1,11 +1,11 @@ pragma solidity ^0.4.24; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IModuleRegistry.sol"; import "./interfaces/IModuleFactory.sol"; import "./interfaces/ISecurityTokenRegistry.sol"; import "./interfaces/IPolymathRegistry.sol"; import "./interfaces/IFeatureRegistry.sol"; -import "./interfaces/IERC20.sol"; import "./libraries/VersionUtils.sol"; import "./storage/EternalStorage.sol"; import "./libraries/Encoder.sol"; diff --git a/contracts/ReclaimTokens.sol b/contracts/ReclaimTokens.sol index 767442829..d1c4516f5 100644 --- a/contracts/ReclaimTokens.sol +++ b/contracts/ReclaimTokens.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; -import "./interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; /** * @title Utility contract to allow owner to retreive any ERC20 sent to the contract @@ -16,6 +16,6 @@ contract ReclaimTokens is Ownable { require(_tokenContract != address(0), "Invalid address"); IERC20 token = IERC20(_tokenContract); uint256 balance = token.balanceOf(address(this)); - require(token.transfer(owner, balance), "Transfer failed"); + require(token.transfer(owner(), balance), "Transfer failed"); } } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 7d24793f3..5e380fb49 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -1,9 +1,9 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IOwnable.sol"; import "./interfaces/ISTFactory.sol"; -import "./interfaces/IERC20.sol"; import "./interfaces/ISecurityTokenRegistry.sol"; import "./storage/EternalStorage.sol"; import "./libraries/Util.sol"; diff --git a/contracts/external/oraclizeAPI.sol b/contracts/external/oraclizeAPI.sol index c8d7a8f18..bc8045879 100644 --- a/contracts/external/oraclizeAPI.sol +++ b/contracts/external/oraclizeAPI.sol @@ -1,15 +1,25 @@ // +// Release targetted at solc 0.4.25 to silence compiler warning/error messages, compatible down to 0.4.22 /* Copyright (c) 2015-2016 Oraclize SRL Copyright (c) 2016 Oraclize LTD + + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,9 +29,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// This api is currently targeted at 0.4.18, please import oraclizeAPI_pre0.4.sol or oraclizeAPI_0.4 where necessary +// This api is currently targeted at 0.4.22 to 0.4.25 (stable builds), 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 +pragma solidity >=0.4.22;// Incompatible compiler version... please select one stated within pragma solidity or use different oraclizeAPI version contract OraclizeI { address public cbAddress; @@ -44,17 +54,23 @@ contract OraclizeAddrResolverI { /* Begin solidity-cborutils + https://github.com/smartcontractkit/solidity-cborutils + MIT License + Copyright (c) 2018 SmartContract ChainLink, Ltd. + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -346,7 +362,11 @@ contract usingOraclize { } function __callback(bytes32 myid, string result, bytes proof) public { return; + // Following should never be reached with a preceding return, however + // this is just a placeholder function, ideally meant to be defined in + // child contract when proofs are used myid; result; proof; // Silence compiler warnings + oraclize = OraclizeI(0); // Additional compiler silence about making function pure/view. } function oraclize_getPrice(string datasource) oraclizeAPI internal returns (uint){ @@ -744,7 +764,7 @@ contract usingOraclize { return oraclize.randomDS_getSessionPubKeyHash(); } - function getCodeSize(address _addr) constant internal returns(uint _size) { + function getCodeSize(address _addr) view internal returns(uint _size) { assembly { _size := extcodesize(_addr) } @@ -963,7 +983,7 @@ contract usingOraclize { } - oraclize_randomDS_setCommitment(queryId, keccak256(delay_bytes8_left, args[1], sha256(args[0]), args[2])); + oraclize_randomDS_setCommitment(queryId, keccak256(abi.encodePacked(delay_bytes8_left, args[1], sha256(args[0]), args[2]))); return queryId; } @@ -1075,7 +1095,7 @@ contract usingOraclize { uint ledgerProofLength = 3+65+(uint(proof[3+65+1])+2)+32; bytes memory keyhash = new bytes(32); copyBytes(proof, ledgerProofLength, 32, keyhash, 0); - if (!(keccak256(keyhash) == keccak256(sha256(context_name, queryId)))) return false; + if (!(keccak256(keyhash) == keccak256(abi.encodePacked(sha256(abi.encodePacked(context_name, queryId)))))) return false; bytes memory sig1 = new bytes(uint(proof[ledgerProofLength+(32+8+1+32)+1])+2); copyBytes(proof, ledgerProofLength+(32+8+1+32), sig1.length, sig1, 0); @@ -1093,7 +1113,7 @@ contract usingOraclize { copyBytes(proof, sig2offset-64, 64, sessionPubkey, 0); bytes32 sessionPubkeyHash = sha256(sessionPubkey); - if (oraclize_randomDS_args[queryId] == keccak256(commitmentSlice1, sessionPubkeyHash)){ //unonce, nbytes and sessionKeyHash match + if (oraclize_randomDS_args[queryId] == keccak256(abi.encodePacked(commitmentSlice1, sessionPubkeyHash))){ //unonce, nbytes and sessionKeyHash match delete oraclize_randomDS_args[queryId]; } else return false; @@ -1212,3 +1232,4 @@ contract usingOraclize { } } +// diff --git a/contracts/helpers/PolyToken.sol b/contracts/helpers/PolyToken.sol index d8f3d48ec..ab71ecfda 100644 --- a/contracts/helpers/PolyToken.sol +++ b/contracts/helpers/PolyToken.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../interfaces/IERC20.sol"; +import "../interfaces/IPoly.sol"; /* Copyright (c) 2016 Smart Contract Solutions, Inc. @@ -64,7 +64,7 @@ library SafeMath { * @dev Implementation of the basic standard token. * @dev https://github.com/ethereum/EIPs/issues/20 */ -contract PolyToken is IERC20 { +contract PolyToken is IPoly { using SafeMath for uint256; // Poly Token parameters diff --git a/contracts/interfaces/IERC20.sol b/contracts/interfaces/IPoly.sol similarity index 98% rename from contracts/interfaces/IERC20.sol rename to contracts/interfaces/IPoly.sol index b1d36463f..3d84a468b 100644 --- a/contracts/interfaces/IERC20.sol +++ b/contracts/interfaces/IPoly.sol @@ -4,7 +4,7 @@ pragma solidity ^0.4.24; * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ -interface IERC20 { +interface IPoly { function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address _owner) external view returns (uint256); diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index 6c0e47c3d..31e5edafa 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -24,7 +24,7 @@ contract MockBurnFactory is TrackedRedemptionFactory { */ function deploy(bytes /*_data*/) external returns(address) { if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Unable to pay setup cost"); + 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*/ diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 452a48b13..9a804772f 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -176,7 +176,7 @@ contract DividendCheckpoint is ICheckpoint, Module { { Dividend storage dividend = dividends[_dividendIndex]; address[] memory investors = ISecurityToken(securityToken).getInvestors(); - uint256 numberInvestors = Math.min256(investors.length, _start.add(_iterations)); + uint256 numberInvestors = Math.min(investors.length, _start.add(_iterations)); for (uint256 i = _start; i < numberInvestors; i++) { address payee = investors[i]; if ((!dividend.claimed[payee]) && (!dividend.dividendExcluded[payee])) { diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 1f7f25cd5..3a981ce28 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.24; import "./DividendCheckpoint.sol"; import "../../interfaces/IOwnable.sol"; -import "../../interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; /** * @title Checkpoint module for issuing ERC20 dividends diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 5fd158c26..10a1fc5a0 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -32,7 +32,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "insufficent allowance"); + 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); diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 315760be1..69859c4f0 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -32,7 +32,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"); + 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); diff --git a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol index d1fa010b7..87f480e09 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol @@ -32,7 +32,7 @@ contract TrackedRedemptionFactory is ModuleFactory { */ function deploy(bytes /* _data */) external returns(address) { if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Insufficent allowance or balance"); + 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); diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol index 1b5daac29..c3ec735cc 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol @@ -32,7 +32,7 @@ contract ScheduledCheckpointFactory 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"); + 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; diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol index 5be77b6e0..9ad339be3 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol @@ -32,7 +32,7 @@ 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"); + 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); diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol index e6d8ed2be..346fe9997 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol @@ -34,7 +34,7 @@ contract SingleTradeVolumeRestrictionTMFactory 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"); + 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"); diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index aa3e6d865..e48a74614 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.24; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; -import "../interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index aca262621..99e0f2d9d 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "../interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IModuleFactory.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "../libraries/VersionUtils.sol"; diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index bfdc73801..900fcef1c 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -29,7 +29,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { */ function deploy(bytes /* _data */) external returns(address) { if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance 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); diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 60373ae37..a22750bc4 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.24; import "./ISTO.sol"; import "../../interfaces/ISecurityToken.sol"; -import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 89f3311d2..37cf37f21 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -30,7 +30,7 @@ contract CappedSTOFactory 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), "Sufficent Allowance is not provided"); //Check valid bytes - can only call module init function CappedSTO cappedSTO = new CappedSTO(msg.sender, address(polyToken)); //Checks that _data is valid (not calling anything it shouldn't) diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index 04640ac58..02b55fe08 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -29,7 +29,7 @@ contract DummySTOFactory 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), "Sufficent Allowance is not provided"); //Check valid bytes - can only call module init function DummySTO dummySTO = new DummySTO(msg.sender, address(polyToken)); //Checks that _data is valid (not calling anything it shouldn't) diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/ISTO.sol index 6ed1d5ba1..111c6fa4c 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/ISTO.sol @@ -2,7 +2,7 @@ pragma solidity ^0.4.24; import "../../Pausable.sol"; import "../Module.sol"; -import "../../interfaces/IERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index 035c4bad5..b78a208ed 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -31,7 +31,7 @@ contract PreSaleSTOFactory 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), "Sufficent Allowance is not provided"); } //Check valid bytes - can only call module init function PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender, address(polyToken)); diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 894744451..b4e0bc203 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -6,7 +6,7 @@ import "../../interfaces/IOracle.sol"; import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; /** * @title STO module for standard capped crowdsale @@ -434,7 +434,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { require(_investmentValue > 0, "No funds were sent"); uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); - uint256 originalUSD = investedUSD; + uint256 spentValue = investedUSD; // Check for minimum investment require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); @@ -469,11 +469,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { } // Calculate spent in base currency (ETH, DAI or POLY) - uint256 spentValue; if (spentUSD == 0) { spentValue = 0; } else { - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, originalUSD), _investmentValue); + spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, spentValue), _investmentValue); } // Return calculated amounts diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index adc3ba628..51dbbc87f 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -35,7 +35,7 @@ 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(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)); diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index d9b1328f7..48c2f3705 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -31,7 +31,7 @@ contract CountTransferManagerFactory is ModuleFactory { */ function deploy(bytes _data) external returns(address) { if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom due to insufficent Allowance 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*/ diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index c15eb52aa..f073dee6f 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -30,7 +30,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"); + 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); diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index f634b33e9..f2a3ddd6a 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -32,7 +32,7 @@ contract ManualApprovalTransferManagerFactory 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"); + 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); diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 1702b6f08..81a9a01fd 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -31,7 +31,7 @@ contract PercentageTransferManagerFactory 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"); + 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*/ diff --git a/contracts/oracles/PolyOracle.sol b/contracts/oracles/PolyOracle.sol index d46242929..45f068a3e 100644 --- a/contracts/oracles/PolyOracle.sol +++ b/contracts/oracles/PolyOracle.sol @@ -33,7 +33,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { event StalePriceUpdate(bytes32 _queryId, uint256 _time, string _result); modifier isAdminOrOwner { - require(admin[msg.sender] || msg.sender == owner, "Address is not admin or owner"); + require(admin[msg.sender] || msg.sender == owner(), "Address is not admin or owner"); _; } diff --git a/contracts/proxy/UpgradeabilityProxy.sol b/contracts/proxy/UpgradeabilityProxy.sol index 0f7806b71..37b64af3e 100644 --- a/contracts/proxy/UpgradeabilityProxy.sol +++ b/contracts/proxy/UpgradeabilityProxy.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./Proxy.sol"; -import "openzeppelin-solidity/contracts/AddressUtils.sol"; +import "openzeppelin-solidity/contracts/utils/Address.sol"; /** * @title UpgradeabilityProxy @@ -32,7 +32,7 @@ contract UpgradeabilityProxy is Proxy { __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(Address.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)), "New version equals to current"); __version = _newVersion; diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index e9782b2d1..9cb54865c 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/math/Math.sol"; -import "../interfaces/IERC20.sol"; +import "../interfaces/IPoly.sol"; import "../interfaces/IModule.sol"; import "../interfaces/IModuleFactory.sol"; import "../interfaces/IModuleRegistry.sol"; @@ -9,9 +9,9 @@ import "../interfaces/IFeatureRegistry.sol"; import "../modules/TransferManager/ITransferManager.sol"; import "../RegistryUpdater.sol"; import "../libraries/Util.sol"; -import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; import "../libraries/TokenLib.sol"; /** @@ -24,7 +24,7 @@ import "../libraries/TokenLib.sol"; * @notice - ST does not inherit from ISecurityToken due to: * @notice - https://github.com/ethereum/solidity/issues/4847 */ -contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, RegistryUpdater { +contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater { using SafeMath for uint256; TokenLib.InvestorDataStorage investorData; @@ -153,7 +153,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr // Require msg.sender to be the specified module type or the owner of the token modifier onlyModuleOrOwner(uint8 _type) { - if (msg.sender == owner) { + if (msg.sender == owner()) { _; } else { require(_isModule(msg.sender, _type)); @@ -203,7 +203,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr address _polymathRegistry ) public - DetailedERC20(_name, _symbol, _decimals) + ERC20Detailed(_name, _symbol, _decimals) RegistryUpdater(_polymathRegistry) { //When it is created, the owner is the STR @@ -365,7 +365,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function withdrawERC20(address _tokenContract, uint256 _value) external onlyOwner { require(_tokenContract != address(0)); IERC20 token = IERC20(_tokenContract); - require(token.transfer(owner, _value)); + require(token.transfer(owner(), _value)); } /** @@ -377,13 +377,13 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ 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); + uint256 currentAllowance = IPoly(polyToken).allowance(address(this), _module); uint256 newAllowance; if (_increase) { - require(IERC20(polyToken).increaseApproval(_module, _change), "IncreaseApproval fail"); + require(IPoly(polyToken).increaseApproval(_module, _change), "IncreaseApproval fail"); newAllowance = currentAllowance.add(_change); } else { - require(IERC20(polyToken).decreaseApproval(_module, _change), "Insufficient allowance"); + require(IPoly(polyToken).decreaseApproval(_module, _change), "Insufficient allowance"); newAllowance = currentAllowance.sub(_change); } emit ModuleBudgetChanged(modulesToData[_module].moduleTypes, _module, currentAllowance, newAllowance); @@ -678,13 +678,10 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr uint256 _value, 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 invalid"); _adjustTotalSupplyCheckpoints(); - totalSupply_ = totalSupply_.add(_value); - balances[_investor] = balances[_investor].add(_value); + _mint(_investor, _value); emit Minted(_investor, _value); - emit Transfer(address(0), _investor, _value); return true; } @@ -720,14 +717,11 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr return false; } - function _burn(address _from, uint256 _value, bytes _data) internal returns(bool) { - require(_value <= balances[_from], "Value too high"); + function _checkAndBurn(address _from, uint256 _value, bytes _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); _adjustTotalSupplyCheckpoints(); - balances[_from] = balances[_from].sub(_value); - totalSupply_ = totalSupply_.sub(_value); + _burn(_from, _value); emit Burnt(_from, _value); - emit Transfer(_from, address(0), _value); return verified; } @@ -737,7 +731,15 @@ 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 invalid"); + require(_checkAndBurn(msg.sender, _value, _data), "Burn invalid"); + } + + function _checkAndBurnFrom(address _from, uint256 _value, bytes _data) internal returns(bool) { + bool verified = _updateTransfer(_from, address(0), _value, _data); + _adjustTotalSupplyCheckpoints(); + _burnFrom(_from, _value); + emit Burnt(_from, _value); + return verified; } /** @@ -747,9 +749,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _data data to indicate validation */ 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 invalid"); + require(_checkAndBurnFrom(_from, _value, _data), "Burn invalid"); } /** @@ -825,13 +825,9 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @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) public onlyController { - require(_to != address(0)); - require(_value <= balances[_from]); bool verified = _updateTransfer(_from, _to, _value, _data); - balances[_from] = balances[_from].sub(_value); - balances[_to] = balances[_to].add(_value); + _transfer(_from, _to, _value); emit ForceTransfer(msg.sender, _from, _to, _value, verified, _log); - emit Transfer(_from, _to, _value); } /** @@ -842,7 +838,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _log data attached to the transfer by controller to emit in event */ function forceBurn(address _from, uint256 _value, bytes _data, bytes _log) public onlyController { - bool verified = _burn(_from, _value, _data); + bool verified = _checkAndBurn(_from, _value, _data); emit ForceBurn(msg.sender, _from, _value, verified, _log); } diff --git a/package.json b/package.json index 744c3bc39..c4517ae4f 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "ethereumjs-testrpc": "^6.0.3", "ethers": "^4.0.7", "fs": "0.0.2", - "openzeppelin-solidity": "1.10.0", + "openzeppelin-solidity": "2.0.0", "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index f9238ffd9..5973ae902 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -180,9 +180,9 @@ contract("CappedSTO", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken_ETH = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken_ETH = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({ from: _blockNo }), 1); @@ -657,9 +657,9 @@ contract("CappedSTO", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken_POLY = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken_POLY = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 830acf600..4472ba5ca 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -119,9 +119,9 @@ contract("Checkpoints", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1a1e7717a..f7c1be722 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -134,9 +134,9 @@ contract("CountTransferManager", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 26adb85b0..c7c6e610f 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -141,9 +141,9 @@ contract("ERC20DividendCheckpoint", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); // Verify that GeneralTransferManager module get added successfully or not diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 261a7fd4b..668a720b4 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -138,9 +138,9 @@ contract("EtherDividendCheckpoint", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index d554891ee..bc95b925d 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -138,9 +138,9 @@ contract('GeneralPermissionManager', accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 3e060c288..ebabdaa3b 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -152,9 +152,9 @@ contract("GeneralTransferManager", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/helpers/contracts/PolyToken.sol b/test/helpers/contracts/PolyToken.sol index e14d5d663..6f39af814 100644 --- a/test/helpers/contracts/PolyToken.sol +++ b/test/helpers/contracts/PolyToken.sol @@ -1,9 +1,9 @@ pragma solidity ^0.4.24; -import "openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; -contract PolyToken is MintableToken { +contract PolyToken is ERC20Mintable { constructor () public { diff --git a/test/i_Issuance.js b/test/i_Issuance.js index ac1fcdd37..61636f4ee 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -149,9 +149,9 @@ contract("Issuance", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 709991b92..4e3b2799f 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -145,9 +145,9 @@ contract("ManualApprovalTransferManager", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 477ce62d5..b30a6b80b 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -310,8 +310,8 @@ contract("ModuleRegistry", accounts => { 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); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase()); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); }); it("Should fail in adding module. Because module is un-verified", async () => { @@ -417,8 +417,8 @@ contract("ModuleRegistry", accounts => { 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); + assert.equal(tx.logs[2].args._ticker, newSymbol.toUpperCase()); + I_SecurityToken2 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); let bytesData = encodeModuleCall( ["uint256", "uint256", "uint256", "string"], diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index b15ee41a0..bc37b4663 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -154,9 +154,9 @@ contract("PercentageTransferManager", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index a89932dc4..b6bdd2928 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -136,9 +136,9 @@ contract("PreSaleSTO", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index ef6b80c51..9af7bd000 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -512,9 +512,9 @@ contract("SecurityTokenRegistry", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); @@ -583,9 +583,9 @@ contract("SecurityTokenRegistry", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - I_SecurityToken002 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken002 = SecurityToken.at(tx.logs[2].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); @@ -952,7 +952,7 @@ contract("SecurityTokenRegistry", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, "POLY", "SecurityToken doesn't get deployed"); }); }); diff --git a/test/o_security_token.js b/test/o_security_token.js index b43db486d..9cee77f80 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -169,9 +169,9 @@ contract("SecurityToken", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); @@ -850,8 +850,8 @@ contract("SecurityToken", accounts => { 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()); + // console.log(tx.logs[1].args._value.toNumber(), currentBalance.toNumber()); + assert.equal(tx.logs[1].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"); @@ -1085,19 +1085,21 @@ contract("SecurityToken", accounts => { 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"); + let eventForceTransfer = tx.logs[1]; + let eventTransfer = tx.logs[0]; + console.log(eventForceTransfer.args); + console.log(eventTransfer.args); + assert.equal(account_controller, eventForceTransfer.args._controller, "Event not emitted as expected"); + assert.equal(account_investor1, eventForceTransfer.args._from, "Event not emitted as expected"); + assert.equal(account_investor2, eventForceTransfer.args._to, "Event not emitted as expected"); + assert.equal(web3.utils.toWei("10", "ether"), eventForceTransfer.args._value, "Event not emitted as expected"); + console.log(eventForceTransfer.args._verifyTransfer); + assert.equal(false, eventForceTransfer.args._verifyTransfer, "Event not emitted as expected"); + assert.equal("reason", web3.utils.hexToUtf8(eventForceTransfer.args._data), "Event not emitted as expected"); + + assert.equal(account_investor1, eventTransfer.args.from, "Event not emitted as expected"); + assert.equal(account_investor2, eventTransfer.args.to, "Event not emitted as expected"); + assert.equal(web3.utils.toWei("10", "ether"), eventTransfer.args.value, "Event not emitted as expected"); }); it("Should fail to freeze controller functionality because not owner", async () => { diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index b9c825b2c..9af8ee539 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -269,9 +269,9 @@ contract("USDTieredSTO", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 0548a6db6..dc9953f31 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -241,9 +241,9 @@ contract("USDTieredSTO Sim", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 7912658a4..82bd68729 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -139,9 +139,9 @@ contract("Concurrent STO", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index 014b44ac2..9ad03aed8 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -151,14 +151,14 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { // (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); + assert.equal(tx.logs[2].args._ticker, symbol1, "SecurityToken doesn't get deployed"); + I_SecurityToken1 = SecurityToken.at(tx.logs[2].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); + assert.equal(tx.logs[2].args._ticker, symbol2, "SecurityToken doesn't get deployed"); + I_SecurityToken2 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); // Printing all the contract addresses console.log(` diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 40b1cced8..264ab44b0 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -151,9 +151,9 @@ contract("SecurityTokenRegistryProxy", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 159564651..197c1d5bf 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -139,9 +139,9 @@ contract("TrackedRedemption", accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index fe06f3f5c..71a5f49ec 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -133,9 +133,9 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 15c01e68c..aaf51a5f4 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -132,9 +132,9 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { }); // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index 5fcc03a74..f5319e474 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -128,9 +128,9 @@ contract('ScheduledCheckpoint', accounts => { 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"); + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); diff --git a/yarn.lock b/yarn.lock index aba68e85b..33dc876ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -73,15 +73,10 @@ 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.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.0.tgz#958584ddb60990c02c97c1bd9d521fce433bb101" + integrity sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg== acorn@^4.0.3: version "4.0.13" @@ -104,10 +99,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 +121,16 @@ ajv@^6.1.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.5.3: + version "6.5.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.5.tgz#cf97cdade71c6399a92c6d6c4177381291b781a1" + integrity sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg== + 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" @@ -984,13 +985,10 @@ 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" + integrity sha512-x247jIuy60/+FtMRvscqfxtVHQf8AGx2hm9c6btkgC0x/hp9yt+teISNhvF8WlwRkCc5yF2fDECH8SIMe8j+GA== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -1088,7 +1086,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" @@ -1369,9 +1367,10 @@ 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" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== checkpoint-store@^1.1.0: version "1.1.0" @@ -1529,6 +1528,7 @@ colors@^1.1.2: 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" @@ -1572,15 +1572,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" @@ -2238,9 +2229,10 @@ 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" + integrity sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ== eslint-import-resolver-node@^0.3.1: version "0.3.2" @@ -2279,9 +2271,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" @@ -2290,17 +2283,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" @@ -2314,9 +2310,10 @@ 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.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.8.0.tgz#91fbf24f6e0471e8fdf681a4d9dd1b2c9f28309b" + integrity sha512-Zok6Bru3y2JprqTNm14mgQ15YQu/SMDkWdnmHfFg770DIUlmMFd/gqqzCHekxzjHZJxXv3tmTpH0C1icaYJsRQ== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.5.3" @@ -2357,9 +2354,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@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" + integrity sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w== dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -2608,9 +2606,10 @@ 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.9" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.9.tgz#82bb075b1b3da847d672426cb24685371389155d" + integrity sha512-GcPAI8yRCx/Sihk9OCBobERCvjnrLtvCIqJRJUuNUDlR81z9vyRS7siJ3gimPi1JUKMscrFBDOul4ZA9NM0jHA== dependencies: "@types/node" "^10.3.2" aes-js "3.0.0" @@ -2777,9 +2776,10 @@ extendr@^2.1.0: 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" @@ -2972,7 +2972,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: @@ -3045,9 +3045,10 @@ 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" + integrity sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg= fsevents@^1.0.0, fsevents@^1.2.2: version "1.2.4" @@ -3441,9 +3442,15 @@ 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" + 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" @@ -3487,9 +3494,10 @@ 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.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" + integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -4329,12 +4337,13 @@ 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" dependencies: - mime-db "~1.37.0" + mime-db "~1.36.0" mime@1.4.1: version "1.4.1" @@ -4766,9 +4775,10 @@ onetime@^2.0.0: 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" +openzeppelin-solidity@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.0.0.tgz#b45dddbdae090f89577598c1a7e7518df61b7ba2" + integrity sha512-SolpxQFArtiYnlSNg3dZ9sz0WVlKtPqSOcJkXRllaZp4+Lpfqz3vxF0yoh7g75TszKPyadqoJmU7+GM/vwh9SA== optimist@^0.6.1: version "0.6.1" @@ -5175,7 +5185,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" @@ -5184,7 +5194,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" @@ -5297,9 +5307,10 @@ 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" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== regexpu-core@^2.0.0: version "2.0.0" @@ -5488,15 +5499,12 @@ 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" + 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" @@ -5543,17 +5551,18 @@ 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: - loose-envify "^1.1.0" 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" -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: version "0.2.0" @@ -6162,9 +6171,10 @@ 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.0" + resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" + integrity sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg== dependencies: ajv "^6.5.3" lodash "^4.17.10" @@ -6374,9 +6384,10 @@ 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" + integrity sha512-p4dCmB/roQaHaRMe7Ihej4/Cdmq7Usi6aZsPv/cc2x7S5bYLSwwpgQBdjz4PjPSgNh8zqLte6ZhWkkW1CEq1iQ== dependencies: ethereumjs-tx "^1.3.4" ethereumjs-wallet "^0.6.0" @@ -6455,10 +6466,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 eca2cb8b7a78354c53b337435e5b546ca7bbc334 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 21 Nov 2018 12:57:50 +0100 Subject: [PATCH 003/119] adding label into module data --- contracts/libraries/TokenLib.sol | 1 + contracts/tokens/SecurityToken.sol | 74 ++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 42e5bebff..8c823ae29 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -16,6 +16,7 @@ library TokenLib { uint8[] moduleTypes; uint256[] moduleIndexes; uint256 nameIndex; + bytes32 label; } // Structures to maintain checkpoints of balances for governance / dividends diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 9cb54865c..3d3e8fa1e 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -213,20 +213,57 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater securityTokenVersion = SemanticVersion(2,0,0); } - /** - * @notice Attachs a module to the SecurityToken - * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it - * @dev to control restrictions on transfers. - * @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 the module. - * @param _budget max amount of ongoing POLY willing to assign to the module. - */ - function addModule( + // /** + // * @notice Attachs a module to the SecurityToken + // * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it + // * @dev to control restrictions on transfers. + // * @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 the module. + // * @param _budget max amount of ongoing POLY willing to assign to the module. + // */ + // function addModule( + // address _moduleFactory, + // bytes _data, + // uint256 _maxCost, + // uint256 _budget + // ) external onlyOwner nonReentrant { + // //Check that the module factory exists in the ModuleRegistry - will throw otherwise + // IModuleRegistry(moduleRegistry).useModule(_moduleFactory); + // IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); + // uint8[] memory moduleTypes = moduleFactory.getTypes(); + // uint256 moduleCost = moduleFactory.getSetupCost(); + // require(moduleCost <= _maxCost, "Invalid cost"); + // //Approve fee for module + // 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 + // ERC20(polyToken).approve(module, _budget); + // //Add to SecurityToken module map + // bytes32 moduleName = moduleFactory.getName(); + // uint256[] memory moduleIndexes = new uint256[](moduleTypes.length); + // uint256 i; + // for (i = 0; i < moduleTypes.length; i++) { + // moduleIndexes[i] = modules[moduleTypes[i]].length; + // modules[moduleTypes[i]].push(module); + // } + // 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); + // } + + function addModuleWithLabel( address _moduleFactory, bytes _data, uint256 _maxCost, - uint256 _budget + uint256 _budget, + bytes32 _label ) external onlyOwner nonReentrant { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); @@ -250,7 +287,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater modules[moduleTypes[i]].push(module); } modulesToData[module] = TokenLib.ModuleData( - moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length + moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length, _label ); names[moduleName].push(module); //Emit log event @@ -258,6 +295,16 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, now); } + + function addModule( + address _moduleFactory, + bytes _data, + uint256 _maxCost, + uint256 _budget + ){ + addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, "NA"); + } + /** * @notice Archives a module attached to the SecurityToken * @param _module address of module to archive @@ -330,12 +377,13 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return bool module archived * @return uint8 module type */ - function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[]) { + function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[], bytes32) { return (modulesToData[_module].name, modulesToData[_module].module, modulesToData[_module].moduleFactory, modulesToData[_module].isArchived, modulesToData[_module].moduleTypes); + modulesToData[_module].label); } /** From 7cae2a1d18e94652a251ef1c53ff0f40d7fceec0 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 22 Nov 2018 12:41:08 +0100 Subject: [PATCH 004/119] fixing test --- contracts/tokens/SecurityToken.sol | 4 ++-- test/o_security_token.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 3d3e8fa1e..ce3528b4d 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -302,7 +302,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _maxCost, uint256 _budget ){ - addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, "NA"); + return addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, ""); } /** @@ -382,7 +382,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater modulesToData[_module].module, modulesToData[_module].moduleFactory, modulesToData[_module].isArchived, - modulesToData[_module].moduleTypes); + modulesToData[_module].moduleTypes, modulesToData[_module].label); } diff --git a/test/o_security_token.js b/test/o_security_token.js index 9cee77f80..a06f8593e 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -311,6 +311,21 @@ contract("SecurityToken", accounts => { I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); }); + 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); @@ -334,6 +349,7 @@ contract("SecurityToken", accounts => { assert.equal(moduleData[2], I_CappedSTOFactory.address); assert.equal(moduleData[3], false); assert.equal(moduleData[4][0], 3); + assert.equal(moduleData[5], 'NA'); }); it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { From 4182cd97c789b7998e61bf2c17d66c6e37209fbf Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 22 Nov 2018 13:22:17 +0100 Subject: [PATCH 005/119] debug test --- contracts/tokens/SecurityToken.sol | 10 +++++----- test/o_security_token.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index ce3528b4d..d6061b01b 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -90,6 +90,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address _module, uint256 _moduleCost, uint256 _budget, + bytes32 _label, uint256 _timestamp ); @@ -262,9 +263,9 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address _moduleFactory, bytes _data, uint256 _maxCost, - uint256 _budget, + uint256 _budget, bytes32 _label - ) external onlyOwner nonReentrant { + ) onlyOwner nonReentrant { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); @@ -292,16 +293,15 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater names[moduleName].push(module); //Emit log event /*solium-disable-next-line security/no-block-members*/ - emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, now); + emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label, now); } - function addModule( address _moduleFactory, bytes _data, uint256 _maxCost, uint256 _budget - ){ + ) external { return addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, ""); } diff --git a/test/o_security_token.js b/test/o_security_token.js index a06f8593e..9ff26e3d3 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -342,14 +342,14 @@ contract("SecurityToken", accounts => { }); describe("Module related functions", async () => { - it("Should get the modules of the securityToken by index", async () => { + it(" Should get the modules of the securityToken by name", 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); - assert.equal(moduleData[5], 'NA'); + assert.equal(moduleData[5], 0x0000000000000000000000000000000000000000); }); it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { From 02a334a85d0fdb7832b07091ba467ad7f76159fc Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 22 Nov 2018 13:54:48 +0100 Subject: [PATCH 006/119] fixing test cases --- test/o_security_token.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/o_security_token.js b/test/o_security_token.js index 9ff26e3d3..79241b93f 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -296,7 +296,8 @@ contract("SecurityToken", accounts => { ); }); - it("Should successfully attach the STO factory with the security token", async () => { + it("Should successfully add module with label", async () => { + let snapId = await takeSnapshot(); startTime = latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); @@ -304,14 +305,18 @@ contract("SecurityToken", accounts => { 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 }); + const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, "stofactory", { 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"); + console.log("module label is .. "+ web3.utils.toAscii(tx.logs[3].args._label)); + assert(web3.utils.toAscii(tx.logs[3].args._label), "stofactory", "label doesnt match" ); I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); }); 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]); From 114b929b32a063fa0d11187dd228f28d3851a9e8 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 22 Nov 2018 13:55:28 +0100 Subject: [PATCH 007/119] testing module label --- test/o_security_token.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/o_security_token.js b/test/o_security_token.js index 79241b93f..a9b746f2b 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -310,7 +310,7 @@ contract("SecurityToken", accounts => { 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"); console.log("module label is .. "+ web3.utils.toAscii(tx.logs[3].args._label)); - assert(web3.utils.toAscii(tx.logs[3].args._label), "stofactory", "label doesnt match" ); + assert(web3.utils.toAscii(tx.logs[3].args._glabel), "stofactory", "label doesnt match" ); I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); From 535d957c136c18433fbc88486daf820f1f8d8f82 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 23 Nov 2018 13:41:31 +0100 Subject: [PATCH 008/119] finish labeling module --- contracts/tokens/SecurityToken.sol | 39 +++--------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index d6061b01b..2d7237f80 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -222,42 +222,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // * @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 the module. // * @param _budget max amount of ongoing POLY willing to assign to the module. + // * @param _label custom module label. // */ - // function addModule( - // address _moduleFactory, - // bytes _data, - // uint256 _maxCost, - // uint256 _budget - // ) external onlyOwner nonReentrant { - // //Check that the module factory exists in the ModuleRegistry - will throw otherwise - // IModuleRegistry(moduleRegistry).useModule(_moduleFactory); - // IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); - // uint8[] memory moduleTypes = moduleFactory.getTypes(); - // uint256 moduleCost = moduleFactory.getSetupCost(); - // require(moduleCost <= _maxCost, "Invalid cost"); - // //Approve fee for module - // 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 - // ERC20(polyToken).approve(module, _budget); - // //Add to SecurityToken module map - // bytes32 moduleName = moduleFactory.getName(); - // uint256[] memory moduleIndexes = new uint256[](moduleTypes.length); - // uint256 i; - // for (i = 0; i < moduleTypes.length; i++) { - // moduleIndexes[i] = modules[moduleTypes[i]].length; - // modules[moduleTypes[i]].push(module); - // } - // 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); - // } function addModuleWithLabel( address _moduleFactory, @@ -296,6 +262,9 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label, now); } + /** + * @notice addModule function will call addModuleWithLabel() with an empty label for backward compatible + */ function addModule( address _moduleFactory, bytes _data, From 8d52ecb20dc6b3bc08c2224528415dc1fa9bebf3 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 23 Nov 2018 16:13:49 +0100 Subject: [PATCH 009/119] fixed test --- test/o_security_token.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/o_security_token.js b/test/o_security_token.js index a9b746f2b..39b026828 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -304,13 +304,13 @@ contract("SecurityToken", accounts => { await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner }); - - const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, "stofactory", { from: token_owner }); - + console.log("0"); + const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, 'stofactory', { from: token_owner }); + console.log("1"); 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"); console.log("module label is .. "+ web3.utils.toAscii(tx.logs[3].args._label)); - assert(web3.utils.toAscii(tx.logs[3].args._glabel), "stofactory", "label doesnt match" ); + assert(web3.utils.toAscii(tx.logs[3].args._label), "stofactory", "label doesnt match"); I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); From ad29b9f7b6a4a40d460ba7235aab85880ea48f56 Mon Sep 17 00:00:00 2001 From: Ricko Date: Tue, 27 Nov 2018 11:52:36 +0100 Subject: [PATCH 010/119] updating addModuleWithLabel adding public --- contracts/tokens/SecurityToken.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 2d7237f80..1a5d1268e 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -231,7 +231,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _maxCost, uint256 _budget, bytes32 _label - ) onlyOwner nonReentrant { + ) public onlyOwner nonReentrant { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); From 6e6b137d51064366f7ab80779d7f23fbb1d9278e Mon Sep 17 00:00:00 2001 From: Ricko Date: Tue, 27 Nov 2018 11:53:54 +0100 Subject: [PATCH 011/119] updateding addModule get rid of return --- contracts/tokens/SecurityToken.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 1a5d1268e..3c27d7d94 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -271,7 +271,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _maxCost, uint256 _budget ) external { - return addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, ""); + addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, ""); } /** From 9b49ba91911e5a69b31efdbfddda731cb354a398 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 29 Nov 2018 12:48:12 +0100 Subject: [PATCH 012/119] adding change log for module labeling --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c5796e34..f9a67e096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,9 @@ All notable changes to this project will be documented in this file. * Add `getReputationOfFactory()` & `getModuleListOfType()` functions to get the array type data from the ModuleRegistry contract. * Add `_setupCost` in `LogGenerateModuleFromFactory` event. * Add new function `getAllModulesByName()`, To get the list of modules having the same name. #198. -* Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 +* Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 +* Add new `_label` param in ST when a module is added so user can customize the label of the module. #428 + ## Fixed * `getAllModulesAndPermsFromTypes()` does not take securityToken address as a parameter anymore. From 62b3573238636027158adad539c14793f24a7808 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 29 Nov 2018 14:06:24 +0100 Subject: [PATCH 013/119] fixed change log adding more info --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9a67e096..7ba2bfe0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Changelog All notable changes to this project will be documented in this file. +# v3.0.0 + +## Added +* Added new function `addModuleWithLabel` which includes a new `_label` param so user can customize the label of the module. #428 + + +## Fixed +* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label +* Fixed event `ModuleAdded` to also emit `_label` +* Fixed function `getModule` to also return the module label + # v1.5.0 - Release Candidate [__1.5.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __15-08-18__ @@ -32,7 +43,7 @@ All notable changes to this project will be documented in this file. * Add `_setupCost` in `LogGenerateModuleFromFactory` event. * Add new function `getAllModulesByName()`, To get the list of modules having the same name. #198. * Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 -* Add new `_label` param in ST when a module is added so user can customize the label of the module. #428 + ## Fixed From 781cf9cda07a2ded3a5e6bea4477ad17d89fb19d Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 29 Nov 2018 18:52:19 +0530 Subject: [PATCH 014/119] changelog fixes --- CHANGELOG.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ba2bfe0f..47f95b85b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,15 @@ # Changelog All notable changes to this project will be documented in this file. -# v3.0.0 +# v3.0.0 - Release Candidate -## Added -* Added new function `addModuleWithLabel` which includes a new `_label` param so user can customize the label of the module. #428 +[__3.0.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __10-11-18__ - -## Fixed -* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label -* Fixed event `ModuleAdded` to also emit `_label` -* Fixed function `getModule` to also return the module label +## SecurityToken +* Added new function `addModuleWithLabel()` which takes an extra param `_label` that used for giving the customize label to the module for display purpose. #428 +* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. +* Fixed event `ModuleAdded` to also emit `_label`. +* Fixed function `getModule` to also return the respective module label. # v1.5.0 - Release Candidate From 517f38ef9e407793030ab5dea0b4f8c9c2605dc4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 17:49:20 +0530 Subject: [PATCH 015/119] 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 9ca0b8a5fa4e7224e167eb5f690d1a3715b4f02a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 17:56:30 +0530 Subject: [PATCH 016/119] 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 7e493eea1a13586c80d6b6df605ebf7b34bef5ab Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:00:25 +0530 Subject: [PATCH 017/119] 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 903cc956c9a484200658ac71eb16ddc773c18949 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:03:13 +0530 Subject: [PATCH 018/119] 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 06ebe79d623660ca1fe62aeda7e8092453b44e96 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:23:20 +0530 Subject: [PATCH 019/119] 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 9fc1454d60e81bf6169cd9f031fcc052f2c819bd Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:27:16 +0530 Subject: [PATCH 020/119] 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 aae8b16b21b9f47d7a53103b5d2ea8e3c330d5f7 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 10 Dec 2018 18:41:25 +0530 Subject: [PATCH 021/119] 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 380a41e5e70cef4351b4b48230b5d1f7d7723b7f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:13:02 +0530 Subject: [PATCH 022/119] 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 7464709f0282e3ca880815e81f5b4b2f172368c1 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:30:49 +0530 Subject: [PATCH 023/119] 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 81c349c337b2ce8c7c808602622c6bbc3d2d6619 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:33:29 +0530 Subject: [PATCH 024/119] 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 10465f74fb3737974ac576027e499aa8e747d771 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:36:04 +0530 Subject: [PATCH 025/119] 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 b3fe71a84d6f3724ba05ea2c9069e3360b827bec Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 13:47:32 +0530 Subject: [PATCH 026/119] 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 28a86946a..6d72e04ba 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) [![Greenkeeper badge](https://badges.greenkeeper.io/PolymathNetwork/polymath-core.svg)](https://greenkeeper.io/) From bb9d09879c0d094ab69b03d1cc9233cd110dfaba Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 14:18:02 +0530 Subject: [PATCH 027/119] 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 4c86bd5353d42c7a0c2807360d6ac3e15e08d9db Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 14:35:04 +0530 Subject: [PATCH 028/119] 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 6d6ea04759c8ef316d9b07d82862c8226c4cd38a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:07:52 +0530 Subject: [PATCH 029/119] Fixed merge conflict --- .circleci/config.yml | 8 +++----- .gitignore | 6 +++++- package.json | 1 + scripts/test.sh | 6 ++++++ truffle-ci.js | 33 +++++++++++++++++++++++++++++++++ yarn.lock | 39 +++++++++++++++++++++++++++++++++++++-- 6 files changed, 85 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 1693ab75c..dac654947 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,8 @@ package-lock.json bridge.log .node-xml* .solcover.js.bk -allFiredEvents \ No newline at end of file +allFiredEvents +extract/ +extract.py +extract.zip +/test-results diff --git a/package.json b/package.json index c4517ae4f..b71496663 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "ethereumjs-abi": "^0.6.5", "fast-csv": "^2.4.1", "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 33dc876ee..46438a6a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1372,6 +1372,11 @@ chardet@^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" @@ -1699,6 +1704,11 @@ cross-spawn@^6.0.5: semver "^5.5.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" @@ -3553,7 +3563,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" @@ -4215,6 +4225,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" @@ -4415,12 +4434,23 @@ mkdirp-promise@^5.0.1: 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, 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" @@ -7131,6 +7161,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 632e6a1b4e0976857a0651308c68dcc815aca2ec Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:19:47 +0530 Subject: [PATCH 030/119] 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 36df0b2d46e50f13778aebbaab849e17b41d14b4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:34:11 +0530 Subject: [PATCH 031/119] 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 20fc4702b2bd7ca3d5472fb37c46a4c283b9f94f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:44:34 +0530 Subject: [PATCH 032/119] 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 069c726383d0b707bd54759cbcdff58f208e22b7 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:46:08 +0530 Subject: [PATCH 033/119] 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 dcaff3c7b0b7a78271b9ae614d98ed62ecc2dec5 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 17:51:23 +0530 Subject: [PATCH 034/119] 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 323dbc9708057f8f182f887ee2a45fa5df567ae4 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 18:06:20 +0530 Subject: [PATCH 035/119] 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 c8899656ab8bd13b60235a611b1bf4f312071f3f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 18:12:49 +0530 Subject: [PATCH 036/119] 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 9eafd65c30d0c0bc827314444cb1a159568708be Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 20:09:16 +0530 Subject: [PATCH 037/119] Fix merge conflict --- .circleci/config.yml | 9 ++++----- .travis.yml | 16 +++++----------- README.md | 2 +- 3 files changed, 10 insertions(+), 17 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 14c03d06b..9a3175771 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,17 +4,11 @@ node_js: cache: directories: - node_modules -matrix: - fast_finish: true -before_install: - - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - - sudo apt-get -y update - - 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 -script: - - npm run test +jobs: + include: + - stage: test + before_script: truffle version + script: 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= diff --git a/README.md b/README.md index 6d72e04ba..28a86946a 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) [![Greenkeeper badge](https://badges.greenkeeper.io/PolymathNetwork/polymath-core.svg)](https://greenkeeper.io/) From 3650f8558d452617f375bc8b4c50a59da0edaeaf Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 20:55:37 +0530 Subject: [PATCH 038/119] 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 4d4d7ae19e55258c1ae2f004d5cdcb7dbb48b89f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 13 Dec 2018 21:01:27 +0530 Subject: [PATCH 039/119] 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 7d8728cc69747e0d0c669151050222fc9318ad69 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Fri, 14 Dec 2018 12:11:15 +0200 Subject: [PATCH 040/119] Fetch poly token from pm registry (#460) * removed _polyAddress from Module constructor * removed _polyAddress from ModuleFactory constructor * fixed tests * reverted changes for MockOracle in tests * updated deploy(), constructor docs * removed polyToken from function params in createInstance.js * added updateFromRegistry to SecurityTokenRegistry * removed polyToken parameter for initialize() * fixed tests * updated setInPolymathRegistry * removed updatePolyTokenAddress * get rid of getPolyToken function * removed updateFromRegistry() * updated CHANGELOG.md * Update CHANGELOG.md * addition of an external function * Fixed typo * Remove duplicate code and optimise a bit --- CHANGELOG.md | 16 +++- contracts/SecurityTokenRegistry.sol | 28 +++---- .../interfaces/ISecurityTokenRegistry.sol | 6 -- contracts/interfaces/IUSDTieredSTOProxy.sol | 5 +- contracts/mocks/MockBurnFactory.sol | 19 ++--- contracts/mocks/MockFactory.sol | 11 ++- contracts/mocks/MockRedemptionManager.sol | 5 +- contracts/mocks/MockWrongTypeFactory.sol | 14 ++-- contracts/mocks/TestSTOFactory.sol | 8 +- .../Checkpoint/ERC20DividendCheckpoint.sol | 5 +- .../ERC20DividendCheckpointFactory.sol | 10 +-- .../Checkpoint/EtherDividendCheckpoint.sol | 5 +- .../EtherDividendCheckpointFactory.sol | 10 +-- .../Experimental/Burn/TrackedRedemption.sol | 5 +- .../Burn/TrackedRedemptionFactory.sol | 10 +-- .../Mixed/ScheduledCheckpoint.sol | 5 +- .../Mixed/ScheduledCheckpointFactory.sol | 10 +-- .../LockupVolumeRestrictionTM.sol | 5 +- .../LockupVolumeRestrictionTMFactory.sol | 12 ++- .../SingleTradeVolumeRestrictionTM.sol | 5 +- .../SingleTradeVolumeRestrictionTMFactory.sol | 11 +-- contracts/modules/Module.sol | 6 +- contracts/modules/ModuleFactory.sol | 21 ++++-- .../GeneralPermissionManager.sol | 4 +- .../GeneralPermissionManagerFactory.sol | 13 ++-- contracts/modules/STO/CappedSTO.sol | 4 +- contracts/modules/STO/CappedSTOFactory.sol | 13 ++-- contracts/modules/STO/DummySTO.sol | 5 +- contracts/modules/STO/DummySTOFactory.sol | 14 ++-- contracts/modules/STO/PreSaleSTO.sol | 5 +- contracts/modules/STO/PreSaleSTOFactory.sol | 16 ++-- .../ProxyFactory/USDTieredSTOProxyFactory.sol | 5 +- contracts/modules/STO/USDTieredSTO.sol | 2 +- contracts/modules/STO/USDTieredSTOFactory.sol | 14 ++-- .../TransferManager/CountTransferManager.sol | 5 +- .../CountTransferManagerFactory.sol | 13 ++-- .../GeneralTransferManager.sol | 5 +- .../GeneralTransferManagerFactory.sol | 13 ++-- .../ManualApprovalTransferManager.sol | 5 +- .../ManualApprovalTransferManagerFactory.sol | 10 +-- .../PercentageTransferManager.sol | 5 +- .../PercentageTransferManagerFactory.sol | 13 ++-- migrations/2_deploy_contracts.js | 23 +++--- test/b_capped_sto.js | 4 +- test/d_count_transfer_manager.js | 4 +- test/e_erc20_dividends.js | 6 +- test/f_ether_dividends.js | 6 +- test/g_general_permission_manager.js | 4 +- test/h_general_transfer_manager.js | 8 +- test/helpers/createInstances.js | 75 ++++++++++--------- test/i_Issuance.js | 6 +- test/j_manual_approval_transfer_manager.js | 8 +- test/k_module_registry.js | 12 +-- test/l_percentage_transfer_manager.js | 6 +- test/m_presale_sto.js | 4 +- test/n_security_token_registry.js | 52 +------------ test/o_security_token.js | 14 ++-- test/p_usd_tiered_sto.js | 6 +- test/q_usd_tiered_sto_sim.js | 2 +- test/r_concurrent_STO.js | 6 +- test/s_v130_to_v140_upgrade.js | 9 +-- test/t_security_token_registry_proxy.js | 3 +- test/u_module_registry_proxy.js | 4 +- test/v_tracked_redemptions.js | 4 +- ...kup_volume_restriction_transfer_manager.js | 4 +- test/x_single_trade_volume_restriction.js | 4 +- test/y_scheduled_checkpoints.js | 2 +- 67 files changed, 308 insertions(+), 364 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f95b85b..9b83d04ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,19 @@ All notable changes to this project will be documented in this file. [__3.0.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __10-11-18__ -## SecurityToken -* Added new function `addModuleWithLabel()` which takes an extra param `_label` that used for giving the customize label to the module for display purpose. #428 -* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. +## Added +* Added new function `addModuleWithLabel()` which takes an extra param `_label` that used for giving the customize label to the module for display purpose. #428 + +## Fixed +* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. * Fixed event `ModuleAdded` to also emit `_label`. -* Fixed function `getModule` to also return the respective module label. +* Fixed function `getModule` to also return the respective module label. +* Replaced `updatePolyTokenAddress()` function with `updateFromRegistry()` in `SecurityTokenRegistry`. + +## Removed +* Removed `_polyAddress` parameter from constructors of all modules and module factories. +* Removed `_polyToken` parameter from `initialize` function in `SecurityTokenRegistry`. + # v1.5.0 - Release Candidate diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 5e380fb49..65197882c 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -5,6 +5,7 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IOwnable.sol"; import "./interfaces/ISTFactory.sol"; import "./interfaces/ISecurityTokenRegistry.sol"; +import "./interfaces/IPolymathRegistry.sol"; import "./storage/EternalStorage.sol"; import "./libraries/Util.sol"; import "./libraries/Encoder.sol"; @@ -161,7 +162,6 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _STFactory is the address of the Proxy contract for Security Tokens * @param _stLaunchFee is the fee in POLY required to launch a token * @param _tickerRegFee is the fee in POLY required to register a ticker - * @param _polyToken is the address of the POLY ERC20 token * @param _owner is the owner of the STR */ function initialize( @@ -169,7 +169,6 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { address _STFactory, uint256 _stLaunchFee, uint256 _tickerRegFee, - address _polyToken, address _owner ) external @@ -177,11 +176,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { { require(!getBool(INITIALIZE),"already initialized"); require( - _STFactory != address(0) && _polyToken != address(0) && _owner != address(0) && _polymathRegistry != address(0), + _STFactory != 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); set(TICKERREGFEE, _tickerRegFee); set(EXPIRYLIMIT, uint256(60 * 1 days)); @@ -190,6 +188,19 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(POLYMATHREGISTRY, _polymathRegistry); _setProtocolVersion(_STFactory, uint8(2), uint8(0), uint8(0)); set(INITIALIZE, true); + _updateFromRegistry(); + } + + /** + * @notice Used to update the polyToken contract address + */ + function updateFromRegistry() external onlyOwner { + _updateFromRegistry(); + } + + function _updateFromRegistry() internal { + address polymathRegistry = getAddress(POLYMATHREGISTRY); + set(POLYTOKEN, IPolymathRegistry(polymathRegistry).getAddress("PolyToken")); } ///////////////////////////// @@ -740,15 +751,6 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); } - /** - * @notice Changes the PolyToken address. Only Polymath. - * @param _newAddress is the address of the polytoken. - */ - function updatePolyTokenAddress(address _newAddress) external onlyOwner { - require(_newAddress != address(0), "Invalid address"); - set(POLYTOKEN, _newAddress); - } - /** * @notice Gets the security token launch fee * @return Fee amount diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 8db01f8ad..c7de4646d 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -169,12 +169,6 @@ interface ISecurityTokenRegistry { */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external; - /** - * @notice Change the PolyToken address - * @param _newAddress Address of the polytoken - */ - function updatePolyTokenAddress(address _newAddress) external; - /** * @notice Gets the security token launch fee * @return Fee amount diff --git a/contracts/interfaces/IUSDTieredSTOProxy.sol b/contracts/interfaces/IUSDTieredSTOProxy.sol index 3aec141a0..480cee059 100644 --- a/contracts/interfaces/IUSDTieredSTOProxy.sol +++ b/contracts/interfaces/IUSDTieredSTOProxy.sol @@ -8,11 +8,10 @@ interface IUSDTieredSTOProxy { /** * @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 + * @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); + function deploySTO(address _securityToken, address _factoryAddress) external returns (address); /** * @notice Used to get the init function signature diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index 31e5edafa..a5b4972d7 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -9,12 +9,14 @@ import "../modules/Experimental/Burn/TrackedRedemptionFactory.sol"; contract MockBurnFactory is TrackedRedemptionFactory { - /** - * @notice Constructor - * @param _polyAddress Address of the polytoken - */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - TrackedRedemptionFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + /** + * @notice Constructor + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + TrackedRedemptionFactory(_setupCost, _usageCost, _subscriptionCost) { } @@ -23,10 +25,9 @@ contract MockBurnFactory is TrackedRedemptionFactory { * @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"); + _takeFee(); //Check valid bytes - can only call module init function - MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, address(polyToken)); + MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender); /*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/MockFactory.sol b/contracts/mocks/MockFactory.sol index 627efb71c..170fdb1e3 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -9,12 +9,15 @@ import "../modules/STO/DummySTOFactory.sol"; contract MockFactory is DummySTOFactory { bool public switchTypes = false; - /** + + /** * @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 - DummySTOFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + DummySTOFactory(_setupCost, _usageCost, _subscriptionCost) { } diff --git a/contracts/mocks/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol index 02fbb2e81..311ffbf0c 100644 --- a/contracts/mocks/MockRedemptionManager.sol +++ b/contracts/mocks/MockRedemptionManager.sol @@ -14,10 +14,9 @@ contract MockRedemptionManager is TrackedRedemption { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - TrackedRedemption(_securityToken, _polyAddress) + constructor (address _securityToken) public + TrackedRedemption(_securityToken) { } diff --git a/contracts/mocks/MockWrongTypeFactory.sol b/contracts/mocks/MockWrongTypeFactory.sol index f04a3a2de..9da441072 100644 --- a/contracts/mocks/MockWrongTypeFactory.sol +++ b/contracts/mocks/MockWrongTypeFactory.sol @@ -10,12 +10,14 @@ import "../libraries/Util.sol"; contract MockWrongTypeFactory is MockBurnFactory { - /** - * @notice Constructor - * @param _polyAddress Address of the polytoken - */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - MockBurnFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + /** + * @notice Constructor + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + MockBurnFactory(_setupCost, _usageCost, _subscriptionCost) { } diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index a8bcbbeb6..da5dc32fc 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -6,10 +6,12 @@ contract TestSTOFactory is DummySTOFactory { /** * @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 - DummySTOFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + DummySTOFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "TestSTO"; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 3a981ce28..7ce4dd3c5 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -47,10 +47,9 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 10a1fc5a0..073ba7e1f 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -10,13 +10,12 @@ contract ERC20DividendCheckpointFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "ERC20DividendCheckpoint"; @@ -31,9 +30,8 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @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)); + _takeFee(); + address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender); /*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 4def51468..06321fdb7 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -27,10 +27,9 @@ contract EtherDividendCheckpoint is DividendCheckpoint { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 69859c4f0..955d5c629 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -10,13 +10,12 @@ contract EtherDividendCheckpointFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "EtherDividendCheckpoint"; @@ -31,9 +30,8 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @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 or balance"); - address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); + _takeFee(); + address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender); /*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/Experimental/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol index bc06a99e9..aaf4b6db7 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -18,10 +18,9 @@ contract TrackedRedemption is IBurn, Module { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol index 87f480e09..2cfaaa6fc 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol @@ -10,13 +10,12 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Constructor - * @param _polyAddress Address of the polytoken * @param _setupCost Setup cost of module * @param _usageCost Usage cost of module * @param _subscriptionCost Monthly cost of module */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "TrackedRedemption"; @@ -31,9 +30,8 @@ contract TrackedRedemptionFactory is ModuleFactory { * @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 or balance"); - address trackedRedemption = new TrackedRedemption(msg.sender, address(polyToken)); + _takeFee(); + address trackedRedemption = new TrackedRedemption(msg.sender); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(trackedRedemption), getName(), address(this), msg.sender, setupCost, now); return address(trackedRedemption); diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index 097a44f50..5c152982b 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -32,10 +32,9 @@ contract ScheduledCheckpoint is ICheckpoint, ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol index c3ec735cc..3e41ef5f0 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol @@ -10,13 +10,12 @@ 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "ScheduledCheckpoint"; @@ -31,9 +30,8 @@ contract ScheduledCheckpointFactory is ModuleFactory { * @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)); + _takeFee(); + address scheduledCheckpoint = new ScheduledCheckpoint(msg.sender); emit GenerateModuleFromFactory(scheduledCheckpoint, getName(), address(this), msg.sender, setupCost, now); return scheduledCheckpoint; } diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 80f44cdb6..57ad67642 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -53,11 +53,10 @@ contract LockupVolumeRestrictionTM is ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) + constructor (address _securityToken) public - Module(_securityToken, _polyAddress) + Module(_securityToken) { } diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol index 9ad339be3..69d4a0e63 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol @@ -10,13 +10,12 @@ contract LockupVolumeRestrictionTMFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "LockupVolumeRestrictionTM"; @@ -31,9 +30,8 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { * @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)); + _takeFee(); + LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, now); return address(lockupVolumeRestrictionTransferManager); @@ -48,7 +46,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { res[0] = 2; return res; } - + /** * @notice Returns the instructions associated with the module */ diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol index b92272167..684840a7a 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol @@ -45,10 +45,9 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor(address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor(address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol index 346fe9997..8c5eb20ce 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol @@ -12,13 +12,12 @@ 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) + constructor(uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "SingleTradeVolumeRestrictionTM"; @@ -33,10 +32,8 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { * @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)); - + _takeFee(); + SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender); 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"); diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index e48a74614..fc79af511 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -1,5 +1,6 @@ pragma solidity ^0.4.24; +import "../RegistryUpdater.sol"; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; @@ -22,12 +23,11 @@ contract Module is IModule { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public { + constructor (address _securityToken) public { securityToken = _securityToken; factory = msg.sender; - polyToken = IERC20(_polyAddress); + polyToken = IERC20(RegistryUpdater(_securityToken).polyToken()); } //Allows owner, factory or permissioned delegate diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index 99e0f2d9d..471ac2eca 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -1,5 +1,6 @@ pragma solidity ^0.4.24; +import "../RegistryUpdater.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IModuleFactory.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; @@ -11,7 +12,6 @@ import "../libraries/VersionUtils.sol"; */ contract ModuleFactory is IModuleFactory, Ownable { - IERC20 public polyToken; uint256 public usageCost; uint256 public monthlySubscriptionCost; @@ -22,9 +22,9 @@ contract ModuleFactory is IModuleFactory, Ownable { string public title; // @notice Allow only two variables to be stored - // 1. lowerBound + // 1. lowerBound // 2. upperBound - // @dev (0.0.0 will act as the wildcard) + // @dev (0.0.0 will act as the wildcard) // @dev uint24 consists packed value of uint8 _major, uint8 _minor, uint8 _patch mapping(string => uint24) compatibleSTVersionRange; @@ -42,10 +42,8 @@ contract ModuleFactory is IModuleFactory, Ownable { /** * @notice Constructor - * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public { - polyToken = IERC20(_polyAddress); + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public { setupCost = _setupCost; usageCost = _usageCost; monthlySubscriptionCost = _subscriptionCost; @@ -127,7 +125,7 @@ contract ModuleFactory is IModuleFactory, Ownable { "Must be a valid bound type" ); require(_newVersion.length == 3); - if (compatibleSTVersionRange[_boundType] != uint24(0)) { + if (compatibleSTVersionRange[_boundType] != uint24(0)) { uint8[] memory _currentVersion = VersionUtils.unpack(compatibleSTVersionRange[_boundType]); require(VersionUtils.isValidVersion(_currentVersion, _newVersion), "Failed because of in-valid version"); } @@ -161,8 +159,15 @@ contract ModuleFactory is IModuleFactory, Ownable { /** * @notice Get the name of the Module */ - function getName() public view returns(bytes32) { + function getName() public view returns (bytes32) { return name; } + function _takeFee() internal { + if (setupCost > 0) { + require(IERC20(RegistryUpdater(msg.sender).polyToken()).transferFrom(msg.sender, owner(), setupCost), + "Insufficient allowance for module fee"); + } + } + } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index f85abf675..f79941a6a 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -26,8 +26,8 @@ contract GeneralPermissionManager is IPermissionManager, Module { /// @notice constructor - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index 900fcef1c..011da5c3e 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -10,10 +10,12 @@ contract GeneralPermissionManagerFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "GeneralPermissionManager"; @@ -28,9 +30,8 @@ contract GeneralPermissionManagerFactory is ModuleFactory { * @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"); - address permissionManager = new GeneralPermissionManager(msg.sender, address(polyToken)); + _takeFee(); + address permissionManager = new GeneralPermissionManager(msg.sender); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); return permissionManager; diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index a22750bc4..e77e98701 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -31,8 +31,8 @@ contract CappedSTO is ISTO, ReentrancyGuard { event SetAllowBeneficialInvestments(bool _allowed); - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 37cf37f21..b7d548b8e 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -11,10 +11,12 @@ contract CappedSTOFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "CappedSTO"; @@ -29,10 +31,9 @@ contract CappedSTOFactory is ModuleFactory { * @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"); + _takeFee(); //Check valid bytes - can only call module init function - CappedSTO cappedSTO = new CappedSTO(msg.sender, address(polyToken)); + CappedSTO cappedSTO = new CappedSTO(msg.sender); //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*/ diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 1b44d2e9b..b4a25e1a6 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -22,10 +22,9 @@ contract DummySTO is ISTO { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index 02b55fe08..b94fd747d 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -11,10 +11,12 @@ contract DummySTOFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "DummySTO"; @@ -23,15 +25,15 @@ contract DummySTOFactory is ModuleFactory { 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"); + _takeFee(); //Check valid bytes - can only call module init function - DummySTO dummySTO = new DummySTO(msg.sender, address(polyToken)); + DummySTO dummySTO = new DummySTO(msg.sender); //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*/ diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 7378fb06b..0c9da3db0 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -19,10 +19,9 @@ contract PreSaleSTO is ISTO { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + constructor (address _securityToken) public + Module(_securityToken) { } diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index b78a208ed..ca587af00 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -11,10 +11,12 @@ contract PreSaleSTOFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "PreSaleSTO"; @@ -30,11 +32,9 @@ contract PreSaleSTOFactory is ModuleFactory { * @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"); - } + _takeFee(); //Check valid bytes - can only call module init function - PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender, address(polyToken)); + PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender); //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*/ @@ -52,7 +52,7 @@ contract PreSaleSTOFactory is ModuleFactory { res[0] = 3; return res; } - + /** * @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 d9a48b87d..d8990d796 100644 --- a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol +++ b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol @@ -12,12 +12,11 @@ contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { /** * @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); + function deploySTO(address _securityToken, address _factoryAddress) external returns (address) { + address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _factoryAddress); return newSecurityTokenAddress; } diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index b4e0bc203..437aede7b 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -163,7 +163,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // STO Configuration // /////////////////////// - constructor (address _securityToken, address _polyAddress, address _factory) public Module(_securityToken, _polyAddress) { + constructor (address _securityToken, address _factory) public Module(_securityToken) { oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; require(_factory != address(0), "In-valid address"); diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 51dbbc87f..4b9cde788 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -13,10 +13,13 @@ contract USDTieredSTOFactory 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 _proxyFactoryAddress Address of the proxy factory */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _proxyFactoryAddress) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _proxyFactoryAddress) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_proxyFactoryAddress != address(0), "0x address is not allowed"); USDTieredSTOProxyAddress = _proxyFactoryAddress; @@ -34,11 +37,10 @@ contract USDTieredSTOFactory is ModuleFactory { * @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"); + _takeFee(); 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 = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, 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*/ diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index b54870251..1d4e2ce1b 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -17,11 +17,10 @@ contract CountTransferManager is ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) + constructor (address _securityToken) public - Module(_securityToken, _polyAddress) + Module(_securityToken) { } diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index 48c2f3705..c61d42ab4 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -11,10 +11,12 @@ contract CountTransferManagerFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "CountTransferManager"; @@ -30,9 +32,8 @@ contract CountTransferManagerFactory is ModuleFactory { * @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"); - CountTransferManager countTransferManager = new CountTransferManager(msg.sender, address(polyToken)); + _takeFee(); + CountTransferManager countTransferManager = new CountTransferManager(msg.sender); 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"); diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 814d54d7b..9e856243b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -68,11 +68,10 @@ contract GeneralTransferManager is ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) + constructor (address _securityToken) public - Module(_securityToken, _polyAddress) + Module(_securityToken) { } diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index f073dee6f..03168efb1 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -10,10 +10,12 @@ 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 */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "GeneralTransferManager"; @@ -29,9 +31,8 @@ contract GeneralTransferManagerFactory is ModuleFactory { * @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)); + _takeFee(); + address generalTransferManager = new GeneralTransferManager(msg.sender); /*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/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index fd888680a..f59590828 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -64,11 +64,10 @@ contract ManualApprovalTransferManager is ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) + constructor (address _securityToken) public - Module(_securityToken, _polyAddress) + Module(_securityToken) { } diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index f2a3ddd6a..7c121e112 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -10,13 +10,12 @@ contract ManualApprovalTransferManagerFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "ManualApprovalTransferManager"; @@ -31,9 +30,8 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { * @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 manualTransferManager = new ManualApprovalTransferManager(msg.sender, address(polyToken)); + _takeFee(); + address manualTransferManager = new ManualApprovalTransferManager(msg.sender); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(manualTransferManager); diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index 162b090de..cea576fb7 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -41,11 +41,10 @@ contract PercentageTransferManager is ITransferManager { /** * @notice Constructor * @param _securityToken Address of the security token - * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) + constructor (address _securityToken) public - Module(_securityToken, _polyAddress) + Module(_securityToken) { } diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 81a9a01fd..624de7212 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -11,10 +11,12 @@ contract PercentageTransferManagerFactory 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) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "PercentageTransferManager"; @@ -30,9 +32,8 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @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"); - PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender, address(polyToken)); + _takeFee(); + PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender); 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"); diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 14bdf9fed..0291a34a6 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -100,9 +100,6 @@ module.exports = function (deployer, network, accounts) { },{ type: 'uint256', name: '_tickerRegFee' - },{ - type: 'address', - name: '_polyToken' },{ type: 'address', name: '_owner' @@ -149,31 +146,31 @@ module.exports = function (deployer, network, accounts) { }).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, 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) - return deployer.deploy(GeneralPermissionManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(GeneralPermissionManagerFactory, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // 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}); + return deployer.deploy(CountTransferManagerFactory, 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) - return deployer.deploy(PercentageTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(PercentageTransferManagerFactory, 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) - return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(EtherDividendCheckpointFactory, 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, {from: PolymathAccount}); + return deployer.deploy(ERC20DividendCheckpointFactory, 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) - return deployer.deploy(ManualApprovalTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(ManualApprovalTransferManagerFactory, 0, 0, 0, {from: PolymathAccount}); }).then(() => { // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, {from: PolymathAccount}); @@ -189,7 +186,7 @@ module.exports = function (deployer, network, accounts) { }).then(()=> { return deployer.deploy(SecurityTokenRegistryProxy, {from: PolymathAccount}); }).then(() => { - let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolyToken, PolymathAccount]); + let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolymathAccount]); return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); }).then(() => { // Assign the address into the SecurityTokenRegistry key @@ -262,7 +259,7 @@ module.exports = function (deployer, network, accounts) { return moduleRegistry.verifyModule(ManualApprovalTransferManagerFactory.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}) + return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, 0, 0, {from: PolymathAccount}) }).then(() => { // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the CappedSTOFactory contract. @@ -277,7 +274,7 @@ module.exports = function (deployer, network, accounts) { 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, usdTieredSTOSetupCost, 0, 0, USDTieredSTOProxyFactory.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. diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 5973ae902..c40ed53de 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -129,11 +129,11 @@ contract("CappedSTO", accounts => { ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 6: Deploy the CappedSTOFactory - I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); + I_CappedSTOFactory = await CappedSTOFactory.new(cappedSTOSetupCost, 0, 0, { from: token_owner }); assert.notEqual( I_CappedSTOFactory.address.valueOf(), diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index f7c1be722..ae7fe9527 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -100,9 +100,9 @@ contract("CountTransferManager", accounts => { ] = instances; // STEP 2: Deploy the CountTransferManager - [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 3: Deploy Paid the CountTransferManager - [P_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); + [P_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); // Printing all the contract addresses console.log(` diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index c7c6e610f..edd9e4282 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -107,8 +107,8 @@ contract("ERC20DividendCheckpoint", accounts => { I_STRProxied ] = instances; - [P_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - [I_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); + [I_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, 0); // Printing all the contract addresses console.log(` @@ -878,7 +878,7 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("should registr a delegate", async () => { - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 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"); assert.equal( diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 668a720b4..cf1f5b073 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -103,8 +103,8 @@ contract("EtherDividendCheckpoint", accounts => { I_STRProxied ] = instances; - [P_EtherDividendCheckpointFactory] = await deployEtherDividendAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); - [I_EtherDividendCheckpointFactory] = await deployEtherDividendAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_EtherDividendCheckpointFactory] = await deployEtherDividendAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); + [I_EtherDividendCheckpointFactory] = await deployEtherDividendAndVerifyed(account_polymath, I_MRProxied, 0); // Printing all the contract addresses console.log(` @@ -792,7 +792,7 @@ contract("EtherDividendCheckpoint", accounts => { }); it("should registr a delegate", async () => { - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 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"); assert.equal( diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index bc95b925d..e255ff0ce 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -103,9 +103,9 @@ contract('GeneralPermissionManager', accounts => { ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 6: Deploy the GeneralDelegateManagerFactory - [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index ebabdaa3b..a6f680738 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -114,10 +114,10 @@ contract("GeneralTransferManager", accounts => { I_STRProxied ] = instances; - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [P_GeneralTransferManagerFactory] = await deployGTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); - [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [P_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); + [P_GeneralTransferManagerFactory] = await deployGTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, 0); + [P_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..db692515f 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -69,7 +69,7 @@ let I_MRProxied; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); -const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; +const STRProxyParameters = ["address", "address", "uint256", "uint256", "address"]; const MRProxyParameters = ["address", "address"]; /// Function use to launch the polymath ecossystem. @@ -105,6 +105,8 @@ async function deployPolyRegistryAndPolyToken(account_polymath, token_owner) { I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens(10000 * Math.pow(10, 18), token_owner); + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { from: account_polymath }); + return new Array(I_PolymathRegistry, I_PolyToken); } @@ -128,7 +130,7 @@ async function deployModuleRegistry(account_polymath) { } async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, 0, 0, { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -163,7 +165,6 @@ async function deploySTR(account_polymath) { I_STFactory.address, initRegFee, initRegFee, - I_PolyToken.address, account_polymath ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }); @@ -192,8 +193,8 @@ 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 }); +export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -206,8 +207,8 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, pol return new Array(I_GeneralTransferManagerFactory); } -export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_CountTransferManagerFactory = await CountTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_CountTransferManagerFactory.address.valueOf(), @@ -219,8 +220,8 @@ export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, return new Array(I_CountTransferManagerFactory); } -export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_ManualApprovalTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -231,8 +232,8 @@ export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxy return new Array(I_ManualApprovalTransferManagerFactory); } -export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { + I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_PercentageTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -243,8 +244,8 @@ export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInst return new Array(I_PercentageTransferManagerFactory); } -export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { + I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_VolumeRestrictionTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -255,8 +256,8 @@ 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 }); +export async function deploySingleTradeVolumeRMAndVerified(accountPolymath, MRProxyInstance, setupCost) { + I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_SingleTradeVolumeRestrictionManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -267,8 +268,8 @@ 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 }); +export async function deployScheduleCheckpointAndVerified(accountPolymath, MRProxyInstance, setupCost) { + I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_ScheduledCheckpointFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -281,8 +282,8 @@ export async function deployScheduleCheckpointAndVerified(accountPolymath, MRPro /// Deploy the Permission Manager -export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -298,8 +299,8 @@ export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, pol /// Deploy the STO Modules -export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_DummySTOFactory = await DummySTOFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_DummySTOFactory = await DummySTOFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_DummySTOFactory.address.valueOf(), @@ -310,8 +311,8 @@ export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance return new Array(I_DummySTOFactory); } -export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_CappedSTOFactory = await CappedSTOFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_CappedSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -323,8 +324,8 @@ 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 }); +export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { + I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_PreSaleSTOFactory.address.valueOf(), @@ -336,10 +337,10 @@ export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstan return new Array(I_PreSaleSTOFactory); } -export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInstance, polyToken, setupCost) { +export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({from: accountPolymath}); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(polyToken, setupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: accountPolymath }); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: accountPolymath }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), @@ -354,8 +355,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 }); +export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -366,8 +367,8 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns return new Array(I_ERC20DividendCheckpointFactory); } -export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), @@ -382,8 +383,8 @@ export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyIns /// Deploy the Burn Module -export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_TrackedRedemptionFactory.address.valueOf(), @@ -396,8 +397,8 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan } -export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_MockBurnFactory = await MockBurnFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_MockBurnFactory = await MockBurnFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_MockBurnFactory.address.valueOf(), @@ -409,8 +410,8 @@ export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyIn return new Array(I_MockBurnFactory); } -export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); +export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( I_MockWrongTypeBurnFactory.address.valueOf(), diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 61636f4ee..31d7b194f 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -108,9 +108,9 @@ contract("Issuance", accounts => { ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 3: Deploy the CappedSTOFactory - [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, 0); // Printing all the contract addresses console.log(` @@ -168,7 +168,7 @@ contract("Issuance", accounts => { 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 }); + I_CappedSTOFactory = await CappedSTOFactory.new(cappedSTOSetupCost, 0, 0, { from: account_polymath }); assert.notEqual( I_CappedSTOFactory.address.valueOf(), diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 4e3b2799f..28fb2f31a 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -104,13 +104,13 @@ contract("ManualApprovalTransferManager", accounts => { ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 3: Deploy the ManualApprovalTransferManagerFactory - [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 4: Deploy the Paid ManualApprovalTransferManagerFactory - [P_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); + [P_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); // STEP 5: Deploy the CountTransferManagerFactory - [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); // Printing all the contract addresses console.log(` diff --git a/test/k_module_registry.js b/test/k_module_registry.js index b30a6b80b..bfdf91eca 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -260,13 +260,13 @@ contract("ModuleRegistry", accounts => { }); it("Should fail in registering the module-- type = 0", async () => { - I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_MockFactory = await MockFactory.new(0, 0, 0, { from: account_polymath }); catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); }); it("Should fail to register the new module because msg.sender is not the owner of the module", async() => { - I_CappedSTOFactory3 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_temp }); + I_CappedSTOFactory3 = await CappedSTOFactory.new(0, 0, 0, { from: account_temp }); catchRevert( I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: token_owner }) ); @@ -292,7 +292,7 @@ contract("ModuleRegistry", accounts => { }); it("Should successfully verify the module -- false", async () => { - I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_CappedSTOFactory1 = await CappedSTOFactory.new(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"); @@ -323,7 +323,7 @@ contract("ModuleRegistry", accounts => { }); 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 }); + I_CappedSTOFactory2 = await CappedSTOFactory.new(0, 0, 0, { from: token_owner }); assert.notEqual( I_CappedSTOFactory2.address.valueOf(), @@ -376,7 +376,7 @@ contract("ModuleRegistry", accounts => { }) it("Should successfully add verified module", async () => { - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(0, 0, 0, { from: account_polymath }); await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); @@ -386,7 +386,7 @@ contract("ModuleRegistry", accounts => { }); 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 }); + I_TestSTOFactory = await TestSTOFactory.new(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 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index bc37b4663..aa11c1ba8 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -113,13 +113,13 @@ contract("PercentageTransferManager", accounts => { ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 3(a): Deploy the PercentageTransferManager - [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, 0); // STEP 4(b): Deploy the PercentageTransferManager - [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); + [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); // Printing all the contract addresses console.log(` diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index b6bdd2928..eadf597c6 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -100,9 +100,9 @@ contract("PreSaleSTO", accounts => { ] = instances; // STEP 4: Deploy the PreSaleSTOFactory - [I_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, 0); // STEP 5: Deploy the paid PresaleSTOFactory - [P_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, 0); // Printing all the contract addresses console.log(` diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 9af7bd000..d4394206a 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -82,7 +82,7 @@ contract("SecurityTokenRegistry", accounts => { const initRegFee = web3.utils.toWei("250"); const newRegFee = web3.utils.toWei("300"); - const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; + const STRProxyParameters = ["address", "address", "uint256", "uint256", "address"]; const STOParameters = ["uint256", "uint256", "uint256", "string"]; // Capped STO details @@ -119,7 +119,7 @@ contract("SecurityTokenRegistry", accounts => { // STEP 8: Deploy the CappedSTOFactory - [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, 0); // Step 9: Deploy the SecurityTokenRegistry I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ from: account_polymath }); @@ -160,7 +160,6 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, initRegFee, - I_PolyToken.address, account_polymath ]); catchRevert( @@ -177,7 +176,6 @@ contract("SecurityTokenRegistry", accounts => { address_zero, initRegFee, initRegFee, - I_PolyToken.address, account_polymath ]); catchRevert( @@ -194,7 +192,6 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, 0, initRegFee, - I_PolyToken.address, account_polymath ]); catchRevert( @@ -211,7 +208,6 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, 0, - I_PolyToken.address, account_polymath ]); catchRevert( @@ -222,30 +218,12 @@ contract("SecurityTokenRegistry", accounts => { ); }); - it("Should successfully update the implementation address -- fail because PolyToken address is 0x", async () => { - let bytesProxy = encodeProxyCall(STRProxyParameters, [ - I_PolymathRegistry.address, - I_STFactory.address, - initRegFee, - initRegFee, - address_zero, - account_polymath - ]); - catchRevert( - I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { - from: account_polymath - }), - "tx-> revert because PolyToken address is 0x" - ); - }); - it("Should successfully update the implementation address -- fail because owner address is 0x", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, - I_PolyToken.address, address_zero ]); catchRevert( @@ -262,7 +240,6 @@ contract("SecurityTokenRegistry", accounts => { address_zero, 0, 0, - address_zero, address_zero ]); catchRevert( @@ -279,7 +256,6 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, initRegFee, - I_PolyToken.address, account_polymath ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { @@ -320,7 +296,6 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, initRegFee, - I_PolyToken.address, account_polymath ), "tx revert -> Can't call the intialize function again" @@ -956,29 +931,6 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Test case for the update poly token", async () => { - it("Should change the polytoken address -- failed because of bad owner", async () => { - catchRevert( - I_STRProxied.updatePolyTokenAddress(dummy_token, { from: account_temp }), - "tx revert -> failed because of bad owner" - ); - }); - - it("Should change the polytoken address -- failed because of 0x address", async () => { - catchRevert( - I_STRProxied.updatePolyTokenAddress("0x0000000000000000000000000000000000000000000", { from: account_polymath }), - "tx revert -> failed because 0x address" - ); - }); - - 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); diff --git a/test/o_security_token.js b/test/o_security_token.js index 39b026828..e1c8d708a 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -133,9 +133,9 @@ contract("SecurityToken", accounts => { ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 3: Deploy the CappedSTOFactory - [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, cappedSTOSetupCost); + [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, cappedSTOSetupCost); // Printing all the contract addresses console.log(` @@ -420,9 +420,9 @@ contract("SecurityToken", accounts => { let FactoryInstances; let GPMAddress = new Array(); - [D_GPM] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [D_GPM_1] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); - [D_GPM_2] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [D_GPM] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); + [D_GPM_1] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); + [D_GPM_2] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); FactoryInstances = [D_GPM, D_GPM_1, D_GPM_2]; // Adding module in the ST for (let i = 0; i < FactoryInstances.length; i++) { @@ -950,7 +950,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); + [I_MockRedemptionManagerFactory] = await deployMockRedemptionAndVerifyed(account_polymath, I_MRProxied, 0); let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); assert.equal(tx.logs[2].args._types[0], burnKey, "fail in adding the burn manager"); I_MockRedemptionManager = MockRedemptionManager.at(tx.logs[2].args._module); @@ -993,7 +993,7 @@ contract("SecurityToken", accounts => { }) it("Should successfully fail in calling the burn functions", async() => { - [I_MockRedemptionManagerFactory] = await deployMockWrongTypeRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_MockRedemptionManagerFactory] = await deployMockWrongTypeRedemptionAndVerifyed(account_polymath, I_MRProxied, 0); let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); I_MockRedemptionManager = MockRedemptionManager.at(tx.logs[2].args._module); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 9af8ee539..1e46c8d1a 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -225,11 +225,11 @@ contract("USDTieredSTO", accounts => { I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 4: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, 0); // STEP 5: Deploy the USDTieredSTOFactory - [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, I_PolyToken.address, STOSetupCost); - [P_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, STOSetupCost); + [P_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, web3.utils.toWei("500")); // 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 diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index dc9953f31..971681b73 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -199,7 +199,7 @@ contract("USDTieredSTO Sim", accounts => { I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); // STEP 5: Deploy the USDTieredSTOFactory - [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, I_PolyToken.address, STOSetupCost); + [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, STOSetupCost); // Step 12: Deploy & Register Mock Oracles I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 82bd68729..636acdc28 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -97,9 +97,9 @@ contract("Concurrent STO", accounts => { // STEP 2: Deploy the STO Factories - [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); - [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); - [I_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, STOSetupCost); + [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, STOSetupCost); + [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, STOSetupCost); + [I_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, STOSetupCost); // Printing all the contract addresses console.log(` diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index 9ad03aed8..3b5b58c3c 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -118,10 +118,10 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { ] = instances; // STEP 4: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, 0); // STEP 5: Deploy the CappedSTOFactory - [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(POLYMATH, I_MRProxied, I_PolyToken.address, STOSetupCost); + [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(POLYMATH, I_MRProxied, STOSetupCost); // Step 12: Mint tokens to ISSUERs await I_PolyToken.getTokens(REGFEE * 2, ISSUER1); @@ -219,7 +219,6 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { it("Should successfully deploy USDTieredSTOFactory", async () => { I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); I_USDTieredSTOFactory = await USDTieredSTOFactory.new( - I_PolyToken.address, STOSetupCost, 0, 0, @@ -247,7 +246,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { 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 }); + I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(STOSetupCost, 0, 0, { from: POLYMATH }); assert.notEqual( I_UpgradedCappedSTOFactory.address.valueOf(), address_zero, @@ -277,7 +276,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { 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, { + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(0, 0, 0, { from: POLYMATH }); assert.notEqual( diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 264ab44b0..5db222274 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -46,7 +46,7 @@ contract("SecurityTokenRegistryProxy", accounts => { const decimals = 18; const transferManagerKey = 2; - const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; + const STRProxyParameters = ["address", "address", "uint256", "uint256", "address"]; async function readStorage(contractAddress, slot) { return await web3.eth.getStorageAt(contractAddress, slot); @@ -105,7 +105,6 @@ contract("SecurityTokenRegistryProxy", accounts => { I_STFactory.address, initRegFee, initRegFee, - I_PolyToken.address, account_polymath ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 6d00b8fe2..0add841b2 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -122,7 +122,7 @@ 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, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, 0, 0, { from: account_polymath }); @@ -160,7 +160,7 @@ contract("ModuleRegistryProxy", accounts => { 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, { + I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(0, 0, 0, { from: account_polymath }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 197c1d5bf..97e8931b4 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -104,8 +104,8 @@ contract("TrackedRedemption", accounts => { // 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")); + [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, 0); + [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 71a5f49ec..2cb1e663e 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -95,9 +95,9 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ] = instances; // STEP 4(c): Deploy the VolumeRestrictionTransferManager - [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, 0); // STEP 4(d): Deploy the VolumeRestrictionTransferManager - [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); + [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index aaf51a5f4..1af45c54c 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -105,8 +105,8 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { ] = 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")); + [I_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, 0); + [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, web3.utils.toWei("500")); }); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index f5319e474..a1b828fb1 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -93,7 +93,7 @@ contract('ScheduledCheckpoint', accounts => { ] = instances; // STEP 2: Deploy the ScheduleCheckpointModule - [I_ScheduledCheckpointFactory] = await deployScheduleCheckpointAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [I_ScheduledCheckpointFactory] = await deployScheduleCheckpointAndVerified(account_polymath, I_MRProxied, 0); // Printing all the contract addresses console.log(` From 585ab5e3c705452af750ed28636f5021d343fce1 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 14 Dec 2018 20:19:41 +0530 Subject: [PATCH 041/119] 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 745747d99f61d8381fa2e018aba85b38e59f442e Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 14 Dec 2018 16:38:46 +0000 Subject: [PATCH 042/119] 2.2.0 merge into 3.0.0 (#473) * Update n_security_token_registry.js * mainnet 2.0.0 registry address * mainnet addresses * Added internal nonce management * nonce tracking fixed * minNonce fixed * Nonce not BN * None init fixed * strMigrator mainnet fixes * Send function fixed * await Optimizations * Skip token deployment if the ST address is known * migrator fixes * Function modifier changes * Minimum investment logic change * Only tickers option * Possibility to skip tickers * Fix * removing CLI from README * Merge remote-tracking branch 'origin/dev-2.1.0' into CLI-st20generator-refactoring * Whitelist refactor * Updated documentation * minor fix * ignore the certificate * Allow unauthenticated repos * Removed travis before install * Configuration by factory allowed only once * Multi mint refactor * Accredit refactor * token_manager command * Non accredited limit refactor + delete old files and packages dependencies * sto_manager command * Support for indivisible tokens * bug fix * test cases for divible token capped STO * CSV sync & ST20generator fix * Updated CLI introduction and link to wiki * Add getTokensSoldByTier * Improvements over mint tokens (parseFloat for divisible tokens) * fixed issue with CLI and added more flattener commands * Update changelog * Typo * readme update * Final CSV refactor * Uploaded Solidified's 2.0.0 auditreport * replaced audit report for 2.0.0 * Added helper view functions * Updated gitignore * Bug fix * Updated changelog * Added test cases * Minor fix * CLI changes for new USDTieredSTO changes * Add transferOwnership to MR (#425) * Add transferOwnership to MR * New test case * added new MR/STR proxy addresses to readme * Typo fix Co-Authored-By: maxsam4 * Allow 0x transfers for MATM * Fix typo * Add support to remote nodes * sto_manager improvements * Minor improvements * Get configure function from ABI * Flow changes * Skip emiting event when no tokens purchased * typo fix * dev-2.1.0 changes * General fixes * Minor fixes * Revert "STRV TM added to migration script" This reverts commit d7e97bbaec22a7af6f99f5dbe6449d28fd742917. * Update CHANGELOG.md * updated description for cappedSTO * fix test * Minor fix * MATM to master (#435) * Allow 0x transfers for MATM * Fix typo * changelog updated and MATM version changed * Update CHANGELOG.md * fixed MATM test w/ version change * Linter fixes * 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 * 2.0.1 MATM deployed to mainnet * Revert "Optimise GTM (#433)" (#436) This reverts commit 42e4a789931d47984429d84b78e40bb3c3320f6a. * Update README.md * MATM CLI support * TokenInfo scripts update * add new core 2.0.0 diagram to readme * Rate changed * changelog updated * Updated tests for rate changes * Issuance test fixed * test cases updated * resolve conflicts in changelog * resolve conflicts in readme * Update README.md * fixed link on readme * Minor fixes * minor fix in readme to reset the MATM * update readme.md Updated from introduction to core up until setting up polymath core * Updated comments * Allow to add TM modules from token_manager * Whitelist from csv fix * Deleted network variable * CLI - Fix at removing modules * CLI - Fix on exit at token selection * CLI - Support for not integer rates on CappedSTO * CLI - Minor fix * fixing audit change request from Mudit * Update script fetch correct solc version * moving multi mint to token manager * replace multi mint to token manager method in cli menu * moving accredit to sto manager file * moving accreditable and nonAccreditable to STO manager * Count transfer manager * Percentage transfer manager * Added docs generation to CI * Path fix * script fix * Testing travis * Testing travis * Testing travis * Testing travis * Testing travis * Testing travis * Testing travis * whitelist to transfer manager * added test cases for adding new holders and removing one at the same time when it is already full. * Update script fetch correct solc version * Added docs generation to CI * Path fix * script fix * Solved merge conflict * Testing travis * Testing travis * Testing travis * Testing travis * Testing travis * Testing travis * WIP * CSV parser * Data folder reorganization * Refactoring and improvements * STO manager refactoring for batch operations * Transfer manager refactoring for batches * Fix * Multi mint in batches * 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 :( * modifyWhitelistMulti for PercentageTM * adjust test cases for adding and removing holders at the same time when max holder amount is full * Bump the version * adjust test logic * 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 * Merged conflicts with master on the CLI * Merge fix * change the type of proxy deployment for USDTieredSTO * Time travel on development network * Fix jump a period of time * bump the version * Show total investors and current percentage ownership at transfer * Modules available are read from ModuleRegistry * Removed sim and fuzz tests from coverage * Time traveling fixes * Add DateTimeLibrary * Error message * Skip DateTime library in code coverage * Update CHANGELOG.md * Update CHANGELOG.md * Fix rounding off errors (#467) * Fixed rounding off errors * Increased tolerance * Reduced tolerance to zero * Comment updated * Tolerance set to 2 * Remove unused contract * Fix test cases * Fix typo * More test fixes * Fix fuzz tests --- .eslintrc.js | 4 +- .gitignore | 5 +- .solcover.js | 4 +- .travis.yml | 27 +- CHANGELOG.md | 52 +- CLI/commands/ST20Generator.js | 1138 ++------------- CLI/commands/TickerRollForward.js | 9 +- CLI/commands/accredit.js | 148 -- CLI/commands/changeNonAccreditedLimit.js | 148 -- CLI/commands/common/common_functions.js | 188 ++- CLI/commands/common/constants.js | 36 + CLI/commands/common/global.js | 76 +- CLI/commands/contract_manager.js | 31 +- CLI/commands/dividends_manager.js | 55 +- CLI/commands/faucet.js | 12 +- CLI/commands/helpers/contract_abis.js | 61 +- CLI/commands/helpers/contract_addresses.js | 2 +- CLI/commands/helpers/csv.js | 35 + CLI/commands/helpers/time.js | 94 ++ CLI/commands/investor_portal.js | 170 +-- CLI/commands/module_manager.js | 447 ------ CLI/commands/multi_mint.js | 280 ---- CLI/commands/permission_manager.js | 87 +- CLI/commands/scripts/script.sh | 19 - CLI/commands/sto_manager.js | 968 +++++++++++++ CLI/commands/strMigrator.js | 691 +++++---- CLI/commands/token_manager.js | 704 +++++++++ CLI/commands/transfer.js | 11 +- CLI/commands/transfer_manager.js | 1277 +++++++++++++++-- CLI/commands/transfer_ownership.js | 10 +- CLI/commands/whitelist.js | 302 ---- .../dividendsExclusions_data.csv | 0 CLI/data/{ => ST}/multi_mint_data.csv | 6 +- .../USDTieredSTO}/accredited_data.csv | 0 .../nonAccreditedLimits_data.csv | 0 CLI/data/STO/capped_sto_data.yml | 14 + CLI/data/STO/usd_tiered_sto_data.yml | 37 + CLI/data/{ => Ticker}/ticker_data.csv | 0 .../{ => Transfer/GTM}/whitelist_data.csv | 0 .../Transfer/PercentageTM/whitelist_data.csv | 10 + CLI/data/capped_sto_data.yml | 35 - CLI/data/usd_tiered_sto_data.yml | 57 - CLI/package.json | 5 +- CLI/polymath-cli.js | 184 +-- CLI/yarn.lock | 421 ++++-- README.md | 261 ++-- .../Polymath Core 2.0.0 Audit Report .pdf | Bin 0 -> 156875 bytes contracts/ModuleRegistry.sol | 12 + contracts/SecurityTokenRegistry.sol | 10 +- contracts/interfaces/IBoot.sol | 10 + .../libraries/BokkyPooBahsDateTimeLibrary.sol | 339 +++++ contracts/mocks/MockBurnFactory.sol | 4 +- contracts/mocks/MockRedemptionManager.sol | 4 +- .../modules/Checkpoint/DividendCheckpoint.sol | 37 +- .../Checkpoint/DividendCheckpointStorage.sol | 43 + .../Checkpoint/ERC20DividendCheckpoint.sol | 43 +- .../ERC20DividendCheckpointFactory.sol | 15 +- .../ERC20DividendCheckpointStorage.sol | 11 + .../Checkpoint/EtherDividendCheckpoint.sol | 29 +- .../EtherDividendCheckpointFactory.sol | 15 +- .../Experimental/Burn/TrackedRedemption.sol | 4 +- .../Burn/TrackedRedemptionFactory.sol | 4 +- .../Mixed/ScheduledCheckpoint.sol | 4 +- .../Mixed/ScheduledCheckpointFactory.sol | 4 +- .../LockupVolumeRestrictionTM.sol | 6 +- .../LockupVolumeRestrictionTMFactory.sol | 4 +- .../SingleTradeVolumeRestrictionTM.sol | 4 +- .../SingleTradeVolumeRestrictionTMFactory.sol | 4 +- contracts/modules/Module.sol | 18 +- contracts/modules/ModuleFactory.sol | 7 +- contracts/modules/ModuleStorage.sol | 30 + .../GeneralPermissionManager.sol | 8 +- .../GeneralPermissionManagerFactory.sol | 4 +- contracts/modules/STO/CappedSTO.sol | 56 +- contracts/modules/STO/CappedSTOFactory.sol | 6 +- contracts/modules/STO/DummySTO.sol | 4 +- contracts/modules/STO/DummySTOFactory.sol | 4 +- contracts/modules/STO/ISTO.sol | 18 +- contracts/modules/STO/ISTOStorage.sol | 24 + contracts/modules/STO/PreSaleSTO.sol | 4 +- contracts/modules/STO/PreSaleSTOFactory.sol | 4 +- .../ProxyFactory/USDTieredSTOProxyFactory.sol | 32 - contracts/modules/STO/USDTieredSTO.sol | 590 +++++--- contracts/modules/STO/USDTieredSTOFactory.sol | 22 +- contracts/modules/STO/USDTieredSTOStorage.sol | 82 ++ .../TransferManager/CountTransferManager.sol | 12 +- .../CountTransferManagerFactory.sol | 6 +- .../GeneralTransferManager.sol | 175 ++- .../GeneralTransferManagerFactory.sol | 15 +- .../GeneralTransferManagerStorage.sol | 53 + .../ManualApprovalTransferManager.sol | 8 +- .../ManualApprovalTransferManagerFactory.sol | 6 +- .../PercentageTransferManager.sol | 10 +- .../PercentageTransferManagerFactory.sol | 4 +- .../proxy/ERC20DividendCheckpointProxy.sol | 31 + .../proxy/EtherDividendCheckpointProxy.sol | 30 + .../proxy/GeneralTransferManagerProxy.sol | 30 + contracts/proxy/OwnedProxy.sol | 91 ++ contracts/proxy/USDTieredSTOProxy.sol | 32 + .../Core Architecture 2.0.0 Diagram.png | Bin 0 -> 60316 bytes migrations/2_deploy_contracts.js | 41 +- package.json | 8 +- scripts/compareStorageLayout.js | 139 ++ scripts/docs.sh | 9 + scripts/{tokenInfo.js => tokenInfo-v1.js} | 62 +- scripts/tokenInfo-v2.js | 108 ++ test/b_capped_sto.js | 74 +- test/d_count_transfer_manager.js | 118 ++ test/e_erc20_dividends.js | 6 +- test/f_ether_dividends.js | 4 +- test/h_general_transfer_manager.js | 124 +- test/helpers/createInstances.js | 53 +- test/i_Issuance.js | 2 +- test/j_manual_approval_transfer_manager.js | 49 +- test/k_module_registry.js | 37 +- test/l_percentage_transfer_manager.js | 2 +- test/n_security_token_registry.js | 1 + test/o_security_token.js | 2 +- test/p_usd_tiered_sto.js | 318 +++- test/q_usd_tiered_sto_sim.js | 18 +- test/r_concurrent_STO.js | 6 +- test/u_module_registry_proxy.js | 5 +- test/v_tracked_redemptions.js | 2 +- ...kup_volume_restriction_transfer_manager.js | 8 +- test/x_single_trade_volume_restriction.js | 726 ---------- test/z_general_permission_manager_fuzzer.js | 669 +++++++++ yarn.lock | 76 +- 127 files changed, 7752 insertions(+), 5058 deletions(-) delete mode 100644 CLI/commands/accredit.js delete mode 100644 CLI/commands/changeNonAccreditedLimit.js create mode 100644 CLI/commands/common/constants.js create mode 100644 CLI/commands/helpers/csv.js create mode 100644 CLI/commands/helpers/time.js delete mode 100644 CLI/commands/module_manager.js delete mode 100644 CLI/commands/multi_mint.js delete mode 100755 CLI/commands/scripts/script.sh create mode 100644 CLI/commands/sto_manager.js create mode 100644 CLI/commands/token_manager.js delete mode 100644 CLI/commands/whitelist.js rename CLI/data/{ => Checkpoint}/dividendsExclusions_data.csv (100%) rename CLI/data/{ => ST}/multi_mint_data.csv (69%) rename CLI/data/{ => STO/USDTieredSTO}/accredited_data.csv (100%) rename CLI/data/{ => STO/USDTieredSTO}/nonAccreditedLimits_data.csv (100%) create mode 100644 CLI/data/STO/capped_sto_data.yml create mode 100644 CLI/data/STO/usd_tiered_sto_data.yml rename CLI/data/{ => Ticker}/ticker_data.csv (100%) rename CLI/data/{ => Transfer/GTM}/whitelist_data.csv (100%) create mode 100644 CLI/data/Transfer/PercentageTM/whitelist_data.csv delete mode 100644 CLI/data/capped_sto_data.yml delete mode 100644 CLI/data/usd_tiered_sto_data.yml create mode 100644 audit reports/Polymath Core 2.0.0 Audit Report .pdf create mode 100644 contracts/interfaces/IBoot.sol create mode 100644 contracts/libraries/BokkyPooBahsDateTimeLibrary.sol 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/STO/ISTOStorage.sol delete mode 100644 contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol create mode 100644 contracts/modules/STO/USDTieredSTOStorage.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 contracts/proxy/USDTieredSTOProxy.sol create mode 100644 docs/images/Core Architecture 2.0.0 Diagram.png create mode 100644 scripts/compareStorageLayout.js rename scripts/{tokenInfo.js => tokenInfo-v1.js} (53%) create mode 100644 scripts/tokenInfo-v2.js 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/.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 diff --git a/.solcover.js b/.solcover.js index 23ac4d3ef..dac86d6e3 100644 --- a/.solcover.js +++ b/.solcover.js @@ -2,8 +2,8 @@ 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'], + skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'libraries/BokkyPooBahsDateTimeLibrary.sol', 'storage', 'modules/Experimental'], forceParse: ['mocks', 'oracles', 'modules/Experimental'] }; diff --git a/.travis.yml b/.travis.yml index 14c03d06b..2265b2d88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,15 +6,22 @@ cache: - node_modules matrix: fast_finish: true -before_install: - - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - - sudo apt-get -y update - - 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 -script: - - 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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b83d04ac..cbc665fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file. * Added new function `addModuleWithLabel()` which takes an extra param `_label` that used for giving the customize label to the module for display purpose. #428 ## Fixed -* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. +* Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. * Fixed event `ModuleAdded` to also emit `_label`. * Fixed function `getModule` to also return the respective module label. * Replaced `updatePolyTokenAddress()` function with `updateFromRegistry()` in `SecurityTokenRegistry`. @@ -17,7 +17,44 @@ All notable changes to this project will be documented in this file. ## Removed * Removed `_polyAddress` parameter from constructors of all modules and module factories. * Removed `_polyToken` parameter from `initialize` function in `SecurityTokenRegistry`. - + +# v2.1.0 - Release Candidate + +[__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. +* 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 `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. +* 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. +* `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.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 @@ -49,17 +86,16 @@ All notable changes to this project will be documented in this file. * Add `getReputationOfFactory()` & `getModuleListOfType()` functions to get the array type data from the ModuleRegistry contract. * Add `_setupCost` in `LogGenerateModuleFromFactory` event. * Add new function `getAllModulesByName()`, To get the list of modules having the same name. #198. -* Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 - +* 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. * 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 @@ -69,7 +105,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__ @@ -93,7 +129,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__ diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index a52499b2f..689b2b27f 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -1,60 +1,22 @@ -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 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; - -/////////////////// -// 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) { common.logAsciiBull(); console.log("********************************************"); console.log("Welcome to the Command-Line ST-20 Generator."); @@ -65,19 +27,19 @@ 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); + } + await tokenManager.executeApp(tokenSymbol); } catch (err) { console.log(err); return; } }; -async function setup(){ +async function setup() { try { securityTokenRegistryAddress = await contracts.securityTokenRegistry(); let securityTokenRegistryABI = abis.securityTokenRegistry(); @@ -88,1049 +50,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); + 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; + 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 }); + // 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')); } - switch (index) { - case 0: - selectedSTO = 'CappedSTO'; - await cappedSTO_launch(); - break; - case 1: - selectedSTO = 'USDTieredSTO'; - await usdTieredSTO_launch(); - break; - case 2: - process.exit(0); - break; - } - } -} - -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(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); } - 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); - } - } - - 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; + tokenName = readlineSync.question('Enter the name for your new token: ', { defaultInput: 'default' }); } - 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.toString() == '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(generateSecurityTokenAction); + 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]; @@ -1148,19 +192,19 @@ 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); - 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(tokenConfig, mintingConfig, stoConfig, remoteNetwork) { - return executeApp(tokenConfig, mintingConfig, stoConfig, remoteNetwork); + 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 deleted file mode 100644 index c4dbd78b6..000000000 --- a/CLI/commands/accredit.js +++ /dev/null @@ -1,148 +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(Issuer, changeAccreditedAction, defaultGasPrice); - 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/changeNonAccreditedLimit.js b/CLI/commands/changeNonAccreditedLimit.js deleted file mode 100644 index b1ececbc7..000000000 --- a/CLI/commands/changeNonAccreditedLimit.js +++ /dev/null @@ -1,148 +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/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]); - - userArray.push(checksummedAddress); - userArray.push(data[1]); - - 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(data[1]); - - badData.push(userArray); - fullFileData.push(userArray) - } - }) - .on("end", function () { - //Add last remainder batch - distribData.push(allocData); - allocData = []; - - changeNonAccreditedLimit(); - }); - - 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 - for (let i = 0; i < distribData.length; i++) { - try { - let investorArray = []; - let 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(Issuer, changeNonAccreditedLimitAction, defaultGasPrice); - 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("---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------\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.`)); - } - } else { - console.log(chalk.red(`Token symbol provided is not a registered Security Token.`)); - } -} diff --git a/CLI/commands/common/common_functions.js b/CLI/commands/common/common_functions.js index af3cdc8fa..fb3db68b7 100644 --- a/CLI/commands/common/common_functions.js +++ b/CLI/commands/common/common_functions.js @@ -19,112 +19,129 @@ async function checkPermission(contractName, functionName, contractRegistry) { 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 } - let result = await securityToken.methods.checkPermission(Issuer.address, contractRegistry.options.address, web3.utils.asciiToHex(permission)).call(); - return result } }; +function getFinalOptions(options) { + if (typeof options != "object") { + options = {} + } + const defaultOptions = { + from: Issuer, + gasPrice: defaultGasPrice, + value: undefined, + factor: 1.2, + minNonce: 0 + } + 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); + } + } + return +} + 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() { - console.log(` -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(@(&&@@@@@@@@@@@@@@@@@@@@@@@@@@(((@&&&&(/@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#(((((((#%%%#@@@@@@@@@@@@@@@@@@@@%##(((/@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%(((((((((((#%%%%%@#@@@@@@@@@@@@(&#####@@@@@@@@%& -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#((((((((((((((##%%%%%%%&&&%%##@%#####%(@@@@@@@#%#& -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%((((((((((((((((((###%%%%%((#####%%%####@@@@@@@###((@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#(((((((((((((((((((((####%%%#((((######%&%@@(##&###(@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#((((((((((((((((((((((((####%%#(((((((#((((((((((((#(@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(%(((((((((((((((((((((((((((######%(((((((((((((#&(/@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#(((((((((((((((((((((((((((((((###############(##%%#@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(#((((##############(((((((((((((((((###################%@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@(&#((#(##################((((((((((((((((((##%%##############@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@/%#(((((((##%((((##############((((((((((((((((((##%%#############%%@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@((((((((((###%%((((((##########(((((((((((((((((((#%%%############%%%#@@@@@@@@@ -@@@@@@@@@@@@@@@@@@%((((((((((####%%%((((((((#######(((((((((((####(((((@%%############%%%#@@@@@@@@@ -@@@@@@@@@####%%%%%#(((((((((#####%%%%(((((((((((###((((#######(((((((((&@@(&#########%%%%&@@@@@@@@@ -@@@@@@@@&(((#####%###(((((((#####%%%%%((((((((####%%%%%%%%&%@%#((((((((@@@@@@(#(####%%%%%%@@@@@@@@@ -@@@@@@@&(((@@@@@@@####(((((######%%%%%%##&########%%%%%#@@@@###(((((#(@@@@@@@@@@@###%%#@@@@@@@@@@@@ -@@@#%&%(((@@@@@@@@#####(((#######%%%%@@@@@@@@@@@((##@@@@@@@@%###((((/@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@#%%&%#@@@@@@@@@@############%%%%@@@@@@@@@@@@@@@@@@@@(@&&&&#####(#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@#%%%%%#((%%%%%%#@@@@@@@@@@@@@@@@@@@@(####%((((%#(@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@&%%%#((((((%%&@@@@@@@@@@@@@@@@@@@@@@###%%#((@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@%%%%((((((((& @@@@@@@@@@@@@@@@@@@@@@@%%&%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@%%(((((&#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@&((###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@#####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@&####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@&&%##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@&&&%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@%##%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@#%####%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + logAsciiBull: function () { + 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; + getNonce: async function (from) { + return (await web3.eth.getTransactionCount(from.address, "pending")); + }, + sendTransaction: async function (action, options) { + await checkPermissions(action); - let block = await web3.eth.getBlock("latest"); - let networkGasLimit = block.gasLimit; + options = getFinalOptions(options); + let gasLimit = await getGasLimit(options, action); - 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} ----`)); + 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); + if (nonce < options.minNonce) { + nonce = minNonce; + } 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(` + .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(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` - ); - }); + ); + }); }, getEventFromLogs: function (jsonInterface, logs, eventName) { let eventJsonInterface = jsonInterface.find(o => o.name === eventName && o.type === 'event'); @@ -135,5 +152,22 @@ 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 = []; + 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; } }; diff --git a/CLI/commands/common/constants.js b/CLI/commands/common/constants.js new file mode 100644 index 000000000..30a3bf699 --- /dev/null +++ b/CLI/commands/common/constants.js @@ -0,0 +1,36 @@ +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 + }, + DEFAULT_BATCH_SIZE: 75, + ADDRESS_ZERO: '0x0000000000000000000000000000000000000000' +}); \ No newline at end of file diff --git a/CLI/commands/common/global.js b/CLI/commands/common/global.js index fb898a708..51972ea92 100644 --- a/CLI/commands/common/global.js +++ b/CLI/commands/common/global.js @@ -1,39 +1,55 @@ 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; + +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; +} - 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 (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); + initialize: async function (network) { + remoteNetwork = network; + if (typeof web3 === 'undefined' || typeof Issuer === 'undefined' || typeof defaultGasPrice === 'undefined') { + if (typeof remoteNetwork !== 'undefined') { + if (!providerValidator(remoteNetwork)) { + console.log("Invalid remote node") + process.exit(0) } - defaultGasPrice = getGasPrice(await web3.eth.net.getId()); + await httpProvider(remoteNetwork, './privKey'); + } else { + await httpProvider("http://localhost:8545", './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 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_abis.js b/CLI/commands/helpers/contract_abis.js index b6c58cc38..8a551b70b 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -7,6 +7,9 @@ let stoInterfaceABI; let cappedSTOABI; let usdTieredSTOABI; let generalTransferManagerABI; +let manualApprovalTransferManagerABI; +let countTransferManagerABI; +let percentageTransferManagerABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -15,29 +18,36 @@ let erc20DividendCheckpointABI; let etherDividendCheckpointABI; let moduleInterfaceABI; let ownableABI; +let iSTOABI; +let iTransferManagerABI; 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; + 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; - 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; + 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"); + console.log('\x1b[31m%s\x1b[0m', "Couldn't find contracts' artifacts. Make sure you ran truffle compile first"); throw err; } @@ -69,6 +79,15 @@ module.exports = { generalTransferManager: function () { return generalTransferManagerABI; }, + manualApprovalTransferManager: function () { + return manualApprovalTransferManagerABI; + }, + countTransferManager: function () { + return countTransferManagerABI; + }, + percentageTransferManager: function () { + return percentageTransferManagerABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, @@ -93,6 +112,12 @@ module.exports = { ownable: function () { return ownableABI; }, + ISTO: function () { + return iSTOABI; + }, + ITransferManager: function () { + return iTransferManagerABI; + }, moduleFactory: function () { return moduleFactoryABI; } diff --git a/CLI/commands/helpers/contract_addresses.js b/CLI/commands/helpers/contract_addresses.js index 1328f8ba9..59a2f39c4 100644 --- a/CLI/commands/helpers/contract_addresses.js +++ b/CLI/commands/helpers/contract_addresses.js @@ -7,7 +7,7 @@ function getPolymathRegistryAddress(networkId) { let result; switch (networkId) { case 1: // MAINNET - result = "0x06595656b93ce14834f0d22b7bbda4382d5ab510"; + result = "0xdfabf3e4793cd30affb47ab6fa4cf4eef26bbc27"; break; case 3: // ROPSTEN result = ""; diff --git a/CLI/commands/helpers/csv.js b/CLI/commands/helpers/csv.js new file mode 100644 index 000000000..a36dcec15 --- /dev/null +++ b/CLI/commands/helpers/csv.js @@ -0,0 +1,35 @@ +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 + 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()); + } else if (web3Utils.isAddress(obj)) { + obj = web3Utils.toChecksumAddress(obj); + } + return obj; +} + +function parse(_csvFilePath, _batchSize) { + // Read file + let input = fs.readFileSync(_csvFilePath); + // Parse csv + let data = csvParse(input, { cast: _cast }); + + return data; +} + +module.exports = parse; \ No newline at end of file diff --git a/CLI/commands/helpers/time.js b/CLI/commands/helpers/time.js new file mode 100644 index 000000000..294f54f67 --- /dev/null +++ b/CLI/commands/helpers/time.js @@ -0,0 +1,94 @@ +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(); + + 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.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`)); + } + } 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) { + 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`)); + } + } else { + console.log(chalk.red(`Time traveling is only possible over develpment network`)); + } +} + +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/commands/investor_portal.js b/CLI/commands/investor_portal.js index 9a5229a7c..cdfa66828 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -3,19 +3,12 @@ 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; let selectedSTO; @@ -39,8 +32,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("********************************************"); @@ -56,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; } @@ -117,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(); @@ -129,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(); @@ -163,13 +155,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,27 +177,27 @@ 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(); } } - 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; } @@ -219,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} @@ -228,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) { @@ -243,11 +235,10 @@ 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()); +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()); console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); } } @@ -255,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()) @@ -287,8 +278,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); } } @@ -296,41 +287,42 @@ 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(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}`; } 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()); @@ -338,13 +330,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}`; } @@ -352,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) { @@ -371,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 `); @@ -416,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]}`); @@ -427,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(User, approveAction, defaultGasPrice); + await common.sendTransaction(approveAction, { from: User }); } let actionBuyTokensWithPoly = currentSTO.methods.buyTokensWithPoly(costWei); - let receipt = await common.sendTransaction(User, actionBuyTokensWithPoly, defaultGasPrice); - 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.`)); @@ -439,8 +431,8 @@ async function investCappedSTO(currency, amount) { } } else { let actionBuyTokens = currentSTO.methods.buyTokens(User.address); - let receipt = await common.sendTransaction(User, actionBuyTokens, defaultGasPrice, costWei); - logTokensPurchasedCappedSTO(receipt); + let receipt = await common.sendTransaction(actionBuyTokens, { from: User, value: costWei }); + logTokensPurchasedCappedSTO(receipt, 'ETH'); } await showTokenInfo(); } @@ -457,11 +449,11 @@ 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) { - 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]; @@ -473,9 +465,9 @@ 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) { + 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)` @@ -487,16 +479,24 @@ 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 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; + } + 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 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 actionBuyWithPoly = currentSTO.methods.buyWithPOLYRateLimited(User.address, costWei, minTokenToBuy); + 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,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(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 actionBuyWithUSD = currentSTO.methods.buyWithUSDRateLimited(User.address, costWei, minTokenToBuy); + 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.buyWithETH(User.address); - let receipt = await common.sendTransaction(User, actionBuyWithETH, defaultGasPrice, costWei); + let actionBuyWithETH = currentSTO.methods.buyWithETHRateLimited(User.address, minTokenToBuy); + let receipt = await common.sendTransaction(actionBuyWithETH, { from: User, value: costWei }); logTokensPurchasedUSDTieredSTO(receipt); } @@ -551,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) { @@ -564,7 +564,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 deleted file mode 100644 index b91541a9c..000000000 --- a/CLI/commands/module_manager.js +++ /dev/null @@ -1,447 +0,0 @@ -// Libraries for terminal prompts -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'); -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(remoteNetwork) { - await global.initialize(remoteNetwork); - - 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= 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(Issuer, mintMultiAction, defaultGasPrice); - 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/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/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/commands/sto_manager.js b/CLI/commands/sto_manager.js new file mode 100644 index 000000000..4f19df76b --- /dev/null +++ b/CLI/commands/sto_manager.js @@ -0,0 +1,968 @@ +const readlineSync = require('readline-sync'); +const chalk = require('chalk'); +const contracts = require('./helpers/contract_addresses'); +const abis = require('./helpers/contract_abis'); +const common = require('./common/common_functions'); +const gbl = require('./common/global'); +const csvParse = require('./helpers/csv'); + +/////////////////// +// 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; + +//////////////////////// +// Artifacts +let securityTokenRegistry; +let moduleRegistry; +let polyToken; +let usdToken; +let securityToken; + +async function executeApp() { + 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`); + } + + 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; + } + } +}; + +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(stoConfig) { + console.log(chalk.blue('Launch STO - Configuration')); + + 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 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 { + optionSelected = stoConfig.type; + } + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'CappedSTO': + let cappedSTO = await cappedSTO_launch(stoConfig); + await cappedSTO_status(cappedSTO); + break; + case 'USDTieredSTO': + let usdTieredSTO = await usdTieredSTO_launch(stoConfig); + await usdTieredSTO_status(usdTieredSTO); + break; + } +} + +//////////////// +// Capped STO // +//////////////// +async function cappedSTO_launch(stoConfig) { + 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 = new web3.utils.BN(await cappedSTOFactory.methods.getSetupCost().call()); + + 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 ${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 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'; + 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 = [gbl.constants.FUND_RAISE_TYPES.POLY]; + } else { + cappedSTOconfig.raiseType = [gbl.constants.FUND_RAISE_TYPES.ETH]; + } + + 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 + '): '); + 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; + } + + if (cappedSTOconfig.startTime == "") cappedSTOconfig.startTime = oneMinuteFromNow; + if (cappedSTOconfig.endTime == "") cappedSTOconfig.endTime = oneMonthFromNow; + + 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()), + web3.utils.toWei(cappedSTOconfig.rate.toString()), + 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 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 = 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'; + 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 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} = ${web3.utils.fromWei(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: ${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}`)); +} + +//////////////////// +// 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 = 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']; + 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] = 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) { + 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) { + 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) { + 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; + } + } + + return tiers; +} + +function limitsConfigUSDTieredSTO() { + let limits = {}; + + let defaultMinimumInvestment = 5; + limits.minimumInvestmentUSD = readlineSync.question(`What is the minimum investment in USD? (${defaultMinimumInvestment}): `, { + limit: function (input) { + return parseFloat(input) > 0; + }, + limitMessage: "Must be greater than zero", + defaultInput: defaultMinimumInvestment + }); + + let nonAccreditedLimit = 2500; + limits.nonAccreditedLimitUSD = readlineSync.question(`What is the default limit for non accredited investors in USD? (${nonAccreditedLimit}): `, { + limit: function (input) { + return parseFloat(input) >= parseFloat(limits.minimumInvestmentUSD); + }, + limitMessage: "Must be greater than minimum investment", + defaultInput: nonAccreditedLimit + }); + + return limits; +} + +function timesConfigUSDTieredSTO(stoConfig) { + let times = {}; + + let oneMinuteFromNow = Math.floor(Date.now() / 1000) + 60; + if (typeof stoConfig === 'undefined') { + 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; + } + if (times.startTime == "") times.startTime = oneMinuteFromNow; + + let oneMonthFromNow = Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60); + if (typeof stoConfig === 'undefined') { + 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; + } + 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(); + 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 = new web3.utils.BN(await usdTieredSTOFactory.methods.getSetupCost().call()); + + 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 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 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 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 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 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 = ""; + 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)`; + } + + let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; + 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, 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, 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}`; + + //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, gbl.constants.FUND_RAISE_TYPES.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: + await changeAccreditedInBatch(currentSTO); + 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); + await common.sendTransaction(changeNonAccreditedLimitAction); + break; + case 4: + await changeNonAccreditedLimitsInBatch(currentSTO); + 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 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`); + } +} + +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 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.')); + 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 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 gbl.constants.FUND_RAISE_TYPES.ETH: + 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: + 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; +} + +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"); +} + +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 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); + 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' }); + 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 (_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/commands/strMigrator.js b/CLI/commands/strMigrator.js index 545455f46..4a8dabfe0 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -4,335 +4,371 @@ 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); - - 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 { - let toSecurityTokenRegistry = await step_instance_toSTR(toStrAddress); - let fromTickerRegistry = await step_instance_fromTR(fromTrAddress); - let tickers = await step_get_registered_tickers(fromTickerRegistry); - await step_register_tickers(tickers, toSecurityTokenRegistry); - let fromSecurityTokenRegistry = await step_instance_fromSTR(fromStrAddress); - let tokens = await step_get_deployed_tokens(fromSecurityTokenRegistry); - await step_launch_STs(tokens, toSecurityTokenRegistry); - } catch (err) { - console.log(err); - return; +let minNonce; + +async function executeApp(toStrAddress, fromTrAddress, fromStrAddress, singleTicker, tokenAddress, onlyTickers, remoteNetwork) { + 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" - }); + 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" - }); + 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) { - let tickers = []; - let expiryTime = await tickerRegistry.methods.expiryLimit().call(); - - let events = await tickerRegistry.getPastEvents('LogRegisterTicker', { fromBlock: 0}); - if (events.length == 0) { - console.log("No ticker registration events were emitted."); - } else { - for (let event of events) { - //for (let index = 0; index < 2; index++) { - //const event = events[index]; - let details = await tickerRegistry.methods.getDetails(event.returnValues._symbol).call(); - let _symbol = event.returnValues._symbol; - let _owner = details[0]; - let _name = details[2]; - let _registrationDate = details[1]; - let _status = details[4]; - - 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: ${event.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 - }); +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 + }); } + } } + } - 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 (readlineSync.keyInYNStrict(`Do you want to migrate a single Ticker?`)) { - let tickerToMigrate = readlineSync.question(`Enter the ticker to migrate: `); - tickers = tickers.filter(t => t.ticker == tickerToMigrate); - } - - 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); - for (const t of tickers) { - 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(Issuer, modifyTickerAction, defaultGasPrice); - 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 (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" - }); + 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) { - let tokens = []; - - let events = await securityTokenRegistry.getPastEvents('LogNewSecurityToken', { fromBlock: 0}); - if (events.length == 0) { - console.log("No security token events were emitted."); - } else { - for (let event of events) { - //for (let index = 0; index < 2; index++) { - //const event = events[index]; - let tokenAddress = event.returnValues._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 web3.eth.getBlock(event.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 mintedEvents = []; - if (gtmEvents.length > 0) { - mintedEvents = await token.getPastEvents('Minted', { fromBlock: event.blockNumber}); - } - - console.log(`--------- SecurityToken launched ---------`); - console.log(`Token address: ${event.returnValues._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: ${event.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 - }); +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 + }); + } } + } - 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) { - if (readlineSync.keyInYNStrict(`Do you want to migrate a single Security Token?`)) { - let tokenToMigrate = readlineSync.question(`Enter the Security Token symbol to migrate: `); - tokens = tokens.filter(t => t.ticker == tokenToMigrate); - } - - if (tickers.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 address: ${t.address}`); - console.log(``); - 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); - // Instancing Security Token - let newTokenAddress = deployTokenReceipt.logs[deployTokenReceipt.logs.length -1].address; //Last log is the ST creation - 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.returnValues._investor, - new web3.utils.BN(gmtEvent.returnValues._fromTime), - new web3.utils.BN(gmtEvent.returnValues._toTime), - new web3.utils.BN(gmtEvent.returnValues._expiryTime), - gmtEvent.returnValues._canBuyFromSTO - ); - let modifyWhitelistReceipt = await common.sendTransaction(Issuer, modifyWhitelistAction, defaultGasPrice); - 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); - 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); - 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); - totalGas = totalGas.add(new web3.utils.BN(modifySecurityTokenReceipt.gasUsed)); - - succeed.push(t); - } catch (error) { - failed.push(t); - console.log(chalk.red(`Transaction failed!!! `)) - console.log(error); - } +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 + 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 ---------- -------------------------------------------- @@ -346,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 --------- -------------------------------------------- @@ -359,25 +395,62 @@ ${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; +} + async function getABIfromEtherscan(_address) { - let urlDomain = network == '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; } module.exports = { - executeApp: async function(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork) { - return executeApp(toStrAddress, fromTrAddress, fromStrAddress, remoteNetwork); - } + 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/commands/token_manager.js b/CLI/commands/token_manager.js new file mode 100644 index 000000000..b74505257 --- /dev/null +++ b/CLI/commands/token_manager.js @@ -0,0 +1,704 @@ +// Libraries for terminal prompts +const readlineSync = require('readline-sync'); +const chalk = require('chalk'); +const stoManager = require('./sto_manager'); +const transferManager = require('./transfer_manager'); +const common = require('./common/common_functions'); +const gbl = require('./common/global'); +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'); +const abis = require('./helpers/contract_abis'); + +let securityTokenRegistry; +let polyToken; +let featureRegistry; +let securityToken; + +let allModules; +let tokenSymbol + +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 featureRegistryAddress = await contracts.featureRegistry(); + let featureRegistryABI = abis.featureRegistry(); + featureRegistry = new web3.eth.Contract(featureRegistryABI, featureRegistryAddress); + featureRegistry.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() { + await showUserInfo(Issuer.address); + while (securityToken) { + allModules = await getAllModules(); + await displayTokenData(); + await displayModules(); + await selectAction(); + } +}; + +async function displayTokenData() { + let displayTokenSymbol = await securityToken.methods.symbol().call(); + let displayTokenDetails = await securityToken.methods.tokenDetails().call(); + let displayVersion = await securityToken.methods.getVersion().call(); + let displayTokenSupply = await securityToken.methods.totalSupply().call(); + let displayInvestorsCount = await securityToken.methods.getInvestorCount().call(); + let displayCurrentCheckpointId = await securityToken.methods.currentCheckpointId().call(); + 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} +- Token symbol: ${displayTokenSymbol.toUpperCase()} +- Token details: ${displayTokenDetails} +- Token version: ${displayVersion[0]}.${displayVersion[1]}.${displayVersion[2]} +- Total supply: ${web3.utils.fromWei(displayTokenSupply)} ${displayTokenSymbol.toUpperCase()} +- Investors count: ${displayInvestorsCount} +- Current checkpoint: ${displayCurrentCheckpointId} +- Transfer frozen: ${displayTransferFrozen ? 'YES' : 'NO'} +- Minting frozen: ${displayMintingFrozen ? 'YES' : 'NO'} +- User balance: ${web3.utils.fromWei(displayUserTokens)} ${displayTokenSymbol.toUpperCase()}`); +} + +async function displayModules() { + // Module Details + let pmModules = allModules.filter(m => 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.question('Enter the id of the checkpoint: ', { + limit: function (input) { + return parseInt(input) > 0 && parseInt(input) <= parseInt(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', `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); + 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 `Mint tokens to multiple addresses from CSV`: + console.log(chalk.yellow(`Investors should be previously whitelisted.`)); + await multiMint(); + 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 multiMint(_csvFilePath, _batchSize) { + let csvFilePath; + if (typeof _csvFilePath !== 'undefined') { + csvFilePath = _csvFilePath; + } else { + csvFilePath = readlineSync.question(`Enter the path for csv data file (${MULTIMINT_DATA_CSV}): `, { + defaultInput: MULTIMINT_DATA_CSV + }); + } + let batchSize; + if (typeof _batchSize !== 'undefined') { + batchSize = _batchSize; + } else { + 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 { + unverifiedData.push(row); + } + } + + 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 (unverifiedData.length > 0) { + console.log("*********************************************************************************************************"); + 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("*********************************************************************************************************"); + } +} + +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', 'Remove a module'); + } + + if (allModules.length > 0) { + options.push('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(archivedModules); + break; + case 'Change module budget': + await changeBudget(allModules); + 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' }); + switch (options[index]) { + case 'Permission Manager': + console.log(chalk.red(` + ********************************* + This option is not yet available. + *********************************`)); + break; + case 'Transfer Manager': + await transferManager.addTransferManagerModule(tokenSymbol) + 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]); + 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; +} + +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' }); + 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 (_tokenSymbol) { + await initialize(_tokenSymbol); + return executeApp(); + }, + multiMint: async function (_tokenSymbol, _csvPath, _batchSize) { + await initialize(_tokenSymbol); + return multiMint(_csvPath, _batchSize); + } +} 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..16af0e34e 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -1,144 +1,1199 @@ -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 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'); +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'; // App flow let tokenSymbol; let securityToken; let securityTokenRegistry; +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`); + } + + 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); + 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 + } + } +} + +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?', { cancel: 'Return' }); + let optionSelected = index != -1 ? options[index] : 'Return'; + console.log('Selected:', optionSelected, '\n'); + switch (optionSelected) { + case 'Disable controller': + if (readlineSync.keyInYNStrict()) { + let disableControllerAction = securityToken.methods.disableController(); + await common.sendTransaction(disableControllerAction); + 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(setControllerAction); + 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(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} + 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; + } +} + +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'; + + switch (moduleNameSelected) { + case 'GeneralTransferManager': + currentTransferManager = new web3.eth.Contract(abis.generalTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await generalTransferManager(); + break; + case 'ManualApprovalTransferManager': + currentTransferManager = new web3.eth.Contract(abis.manualApprovalTransferManager(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await manualApprovalTransferManager(); + 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); + //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; + } +} + +async function addTransferManagerModule() { + 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?`)) { + let bytes = web3.utils.fromAscii('', 16); + switch (options[index]) { + 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}); + 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); + 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}`)); + } +} + +async function generalTransferManager() { + console.log(chalk.blue(`General Transfer Manager at ${currentTransferManager.options.address}`), '\n'); + + // 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(); + let displayDefaults = await currentTransferManager.methods.defaults().call(); + let 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}`); + // ------------------ + + 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 { + 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?', { cancel: 'Return' }); + 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) { + 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 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); + 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': + await modifyWhitelistInBatch(); + 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); + }, + 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'); + 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(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(changeAllowAllTransfersAction); + 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!`)); + } + break; + case 'Allow all whitelist transfers': + case 'Disallow all whitelist transfers': + let changeAllowAllWhitelistTransfersAction = currentTransferManager.methods.changeAllowAllWhitelistTransfers(!displayAllowAllWhitelistTransfers); + 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!`)); + } else { + console.log(chalk.green(`Transfers are restricted by time locks from whitelist!`)); + } + break; + case 'Allow all whitelist issuances': + case 'Disallow all whitelist issuances': + let changeAllowAllWhitelistIssuancesAction = currentTransferManager.methods.changeAllowAllWhitelistIssuances(!displayAllowAllWhitelistIssuances); + 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!`)); + } else { + console.log(chalk.green(`Issuances are restricted by time locks from whitelist!`)); + } + break; + case 'Allow all burn transfers': + case 'Disallow all burn transfers': + let changeAllowAllBurnTransfersAction = currentTransferManager.methods.changeAllowAllBurnTransfers(!displayAllowAllBurnTransfers); + 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!`)); + } else { + console.log(chalk.green(`The burning mechanism is deactivated!`)); + } + break; + } +} + +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 + }); + 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(',')} `)); + } + 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 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('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`); + } +} + +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; -async function executeApp(remoteNetwork) { - await global.initialize(remoteNetwork); - + 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'); + + // 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 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': + 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': + 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(); + + // 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) { + 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")); +} +*/ + +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)); +} + +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"); +} - await setup(); - try { - await start_explorer(); - } catch (err) { - console.log(err); - return; - } -}; - -async function setup(){ +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 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."); + 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"); +async function selectToken() { + let result = null; - if (!tokenSymbol) - tokenSymbol = readlineSync.question('Enter the token symbol: '); + 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 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 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; + } - let forcedTransferDisabled = await securityToken.methods.controllerDisabled().call(); + return result; +} - 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`)); - } - 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); - } - } else { - console.log(chalk.red(`Controller featueres are permanently disabled for this token.`)) - tokenSymbol = undefined; - } - } +async function logTotalInvestors() { + let investorsCount = await securityToken.methods.getInvestorCount().call(); + console.log(chalk.yellow(`Total investors at the moment: ${investorsCount}`)); +} - //Restart - await start_explorer(); +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(type, remoteNetwork) { - return executeApp(type, remoteNetwork); + 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/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 deleted file mode 100644 index 4750adffa..000000000 --- a/CLI/commands/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(Issuer, modifyWhitelistMultiAction, defaultGasPrice); - 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/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 69% rename from CLI/data/multi_mint_data.csv rename to CLI/data/ST/multi_mint_data.csv index 0b157b164..8b27f06b0 100644 --- a/CLI/data/multi_mint_data.csv +++ b/CLI/data/ST/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 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/STO/capped_sto_data.yml b/CLI/data/STO/capped_sto_data.yml new file mode 100644 index 000000000..41653c9ff --- /dev/null +++ b/CLI/data/STO/capped_sto_data.yml @@ -0,0 +1,14 @@ +# 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/STO/usd_tiered_sto_data.yml b/CLI/data/STO/usd_tiered_sto_data.yml new file mode 100644 index 000000000..29655c5bf --- /dev/null +++ b/CLI/data/STO/usd_tiered_sto_data.yml @@ -0,0 +1,37 @@ +# type -> 'CappedSTO' for cappedSTO, 'USDTieredSTO' for USDTieredSTO +type: 'USDTieredSTO' + +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 -> 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: + # 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 -> Minimun investment in USD. + minimumInvestmentUSD: 5 + # nonAccreditedLimitUSD -> Limit in USD for non-accredited investors + nonAccreditedLimitUSD: 10000 + +times: + # 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: '' \ No newline at end of file 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 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 diff --git a/CLI/data/capped_sto_data.yml b/CLI/data/capped_sto_data.yml deleted file mode 100644 index 6be0c0f66..000000000 --- a/CLI/data/capped_sto_data.yml +++ /dev/null @@ -1,35 +0,0 @@ -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 diff --git a/CLI/data/usd_tiered_sto_data.yml b/CLI/data/usd_tiered_sto_data.yml deleted file mode 100644 index 305167bd7..000000000 --- a/CLI/data/usd_tiered_sto_data.yml +++ /dev/null @@ -1,57 +0,0 @@ -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 - -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 - - # 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: '' - - # 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 ] - - # limits - # minimumInvestmentUSD -> minimum investment (in USD) - minimumInvestmentUSD: 5 - # nonAccreditedLimitUSD -> limit for non accredited insvestors (in USD) - nonAccreditedLimitUSD: 10000 - - #times - # startTime -> start time for the STO (Unix Epoch time) - startTime: '' - # endTime -> end time for the STO (Unix Epoch time) - endTime: '' \ No newline at end of file diff --git a/CLI/package.json b/CLI/package.json index 9eee76624..4dfcbf3a4 100644 --- a/CLI/package.json +++ b/CLI/package.json @@ -11,10 +11,13 @@ "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", "request": "^2.88.0", "request-promise": "^4.2.2", - "web3": "1.0.0-beta.34" + "table": "^5.1.1", + "web3": "1.0.0-beta.35" } } diff --git a/CLI/polymath-cli.js b/CLI/polymath-cli.js index 49f578df0..d2b4c68fa 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -1,154 +1,176 @@ #!/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'); -var st20generator = require('./commands/ST20Generator'); -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'); +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'); program - .version('0.0.1') + .version('1.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') .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
', '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) { - 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; + .action(async function (cmd) { + await gbl.initialize(program.remoteNode); + await st20generator.executeApp(cmd.ticker, cmd.transferOwnership, cmd.tokenName, cmd.details, cmd.divisible); + }); + +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') + .description('Wizard-like script that will guide technical users in the creation of an STO') + .action(async function (cmd) { + await gbl.initialize(program.remoteNode); + 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); } - await st20generator.executeApp(tokenConfig, mintingConfig, stoCofig, program.remoteNode); }); program .command('faucet [beneficiary] [amount]') .alias('f') .description('Poly faucet for local private netwtorks') - .action(async function(beneficiary, amount) { - await faucet.executeApp(beneficiary, amount, program.remoteNode); + .action(async function (beneficiary, amount) { + await gbl.initialize(program.remoteNode); + await faucet.executeApp(beneficiary, amount); }); 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) { - await investor_portal.executeApp(investor, privateKey, symbol, currency, amount, program.remoteNode); - }); - -program - .command('module_manager') - .alias('mm') - .description('View modules attached to a token and their status') - .action(async function() { - await module_manager.executeApp(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 - .command('multi_mint [batchSize]') - .alias('mi') - .description('Distribute tokens to previously whitelisted investors') - .action(async function(tokenSymbol, batchSize) { - shell.exec(`${__dirname}/commands/scripts/script.sh Multimint ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; + .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); + 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 .command('transfer ') .alias('t') .description('Transfer ST tokens to another account') - .action(async function(tokenSymbol, transferTo, transferAmount) { - await transfer.executeApp(tokenSymbol, transferTo, transferAmount, program.remoteNode); + .action(async function (tokenSymbol, transferTo, transferAmount) { + await gbl.initialize(program.remoteNode); + await transfer.executeApp(tokenSymbol, transferTo, transferAmount); }); program .command('transfer_ownership ') .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); - }); - -program - .command('whitelist [batchSize]') - .alias('w') - .description('Mass-update a whitelist of allowed/known investors') - .action(async function(tokenSymbol, batchSize) { - shell.exec(`${__dirname}/commands/scripts/script.sh Whitelist ${tokenSymbol} ${batchSize} ${program.remoteNode}`); + .action(async function (contractAddress, transferTo) { + await gbl.initialize(program.remoteNode); + await transfer_ownership.executeApp(contractAddress, transferTo); }); program .command('dividends_manager [dividendsType]') .alias('dm') .description('Runs dividends_manager') - .action(async function(dividendsType) { - await dividends_manager.executeApp(dividendsType, program.remoteNode); + .action(async function (dividendsType) { + await gbl.initialize(program.remoteNode); + await dividends_manager.executeApp(dividendsType); }); program .command('transfer_manager') .alias('tm') + .option('-t, --securityToken ', 'Selects a ST to manage transfer modules') .description('Runs transfer_manager') - .action(async function() { - await transfer_manager.executeApp(program.remoteNode); + .action(async function (cmd) { + await gbl.initialize(program.remoteNode); + await transfer_manager.executeApp(cmd.securityToken); }); program .command('contract_manager') .alias('cm') .description('Runs contract_manager') - .action(async function() { - await contract_manager.executeApp(program.remoteNode); - }); - -program - .command('accredit [batchSize]') - .alias('a') - .description('Runs accredit') - .action(async function(tokenSymbol, batchSize) { - shell.exec(`${__dirname}/commands/scripts/script.sh Accredit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; - }); - -program - .command('nonAccreditedLimit [batchSize]') - .alias('nal') - .description('Runs changeNonAccreditedLimit') - .action(async function(tokenSymbol, batchSize) { - shell.exec(`${__dirname}/commands/scripts/script.sh NonAccreditedLimit ${tokenSymbol} ${batchSize} ${program.remoteNode}`);; + .action(async function () { + await gbl.initialize(program.remoteNode); + await contract_manager.executeApp(); }); program .command('strMigrator [toStrAddress] [fromTrAddress] [fromStrAddress]') + .option('-tick, --singleTicker ', 'It only reads and migrates the ticker and token for given token symbol') + .option('-tok, --tokenAddress ', 'Migrated security token address. It skips all steps until modifySecurityToken') + .option('-ot, --onlyTickers', 'Only migrate tickers without a launched token') .alias('str') .description('Runs STR Migrator') - .action(async function(toStrAddress, fromTrAddress, fromStrAddress) { - await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress, program.remoteNode); + .action(async function (toStrAddress, fromTrAddress, fromStrAddress, cmd) { + await strMigrator.executeApp(toStrAddress, fromTrAddress, fromStrAddress, cmd.singleTicker, cmd.tokenAddress, cmd.onlyTickers, program.remoteNode); }); program .command('permission_manager') .alias('pm') .description('Runs permission_manager') - .action(async function() { - await permission_manager.executeApp(program.remoteNode); + .action(async function () { + await gbl.initialize(program.remoteNode); + 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); diff --git a/CLI/yarn.lock b/CLI/yarn.lock index 9a48fd1a5..82d60b57f 100644 --- a/CLI/yarn.lock +++ b/CLI/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@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== + accepts@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" @@ -20,7 +25,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== @@ -58,6 +78,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" @@ -422,6 +447,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" @@ -618,6 +648,22 @@ eth-lib@0.2.7: elliptic "^6.4.0" xhr-request-promise "^0.1.2" +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" @@ -695,6 +741,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" @@ -988,6 +1039,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" @@ -1046,6 +1102,11 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +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" @@ -1061,6 +1122,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" @@ -1096,7 +1162,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== @@ -1437,6 +1503,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" @@ -1572,6 +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== +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" @@ -1680,6 +1756,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.2" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629" @@ -1715,6 +1800,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" @@ -1722,6 +1815,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" @@ -1762,6 +1862,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" @@ -1887,6 +1997,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" @@ -1943,87 +2060,87 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -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= +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.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= +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.34" - web3-utils "1.0.0-beta.34" + web3-eth-iban "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -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= +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.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-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.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= +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.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= +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.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-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.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= +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.34" + web3-core-helpers "1.0.0-beta.35" -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= +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.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-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.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= +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: 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-core-helpers "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -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= +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" @@ -2031,111 +2148,111 @@ web3-eth-accounts@1.0.0-beta.34: scrypt.js "0.2.0" underscore "1.8.3" uuid "2.0.1" - 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-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.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= +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.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= + 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.34" + web3-utils "1.0.0-beta.35" -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= +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.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-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.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= +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.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= + 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.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.34" + web3-core-helpers "1.0.0-beta.35" -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= +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.34" + web3-core-helpers "1.0.0-beta.35" 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= +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.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-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.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= +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" @@ -2145,18 +2262,18 @@ web3-utils@1.0.0-beta.34: underscore "1.8.3" utf8 "2.1.1" -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" +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" diff --git a/README.md b/README.md index 28a86946a..51610e9d4 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,22 @@ ![Polymath logo](Polymath.png) # Polymath Core - The Polymath Core smart contracts provide a system for launching regulatory-compliant securities tokens on a decentralized blockchain. This particular repository is the implementation of a system that allows for the creation of ST-20-compatible tokens. This system has a modular design that promotes a variety of pluggable components for various types of issuances, legal requirements, and offering processes. +## Introduction to Security Tokens + +### What is a Security token? +A Security Token shares many of the characteristics of both fungible (erc20) and non-fungible tokens (erc721). Security tokens are designed to represent complete or fractional ownership interests in assets and/or entities. While utility tokens have no limitations on who can send or receive the token, security tokens are subject to many restrictions based on identity, jurisdiction and asset category. +### Security Tokens Vs. Utility Tokens? +The concept of utility tokens is fairly well understood in the blockchain space today. Utility tokens represent access to a network, and your token purchase represents the ability to buy goods or services from that network- Think of when you purchase a arcade token to allow you to play an arcade game machine. Utility tokens give you that same type of access to a product or service. On the other hand, security tokens represent complete or fractional ownership in an asset (such as shares in a company, a real-estate asset, artwork, etc). Such as having a stake in a company, real estate, or intellectual property can all be represented by security tokens. Security tokens offer the benefit of bringing significant transparency over traditional paper shares through the use of the blockchain and its associated public ledger. Security token structure, distribution, or changes that could affect investors are now accessible to all via the blockchain. # ST-20 Interface Overview ## Description An ST-20 token is an Ethereum-based token implemented on top of the ERC-20 protocol that adds the ability for tokens to control transfers based on specific rules. ST-20 tokens rely on Transfer Managers to determine the ruleset the token should apply in order to allow or deny a transfer, be it between the issuer and investors, in a peer to peer exchange, or a transaction with an exchange. ## How it works -ST-20 tokens must implement a `verifyTransfer` method which will be called when attempting to execute a `transfer` or `transferFrom` method. The `verifyTransfer` method will determine whether that transaction can be completed or not. The implementation of `verifyTransfer` can take many forms, but the default approach is a whitelist controlled by the `GeneralTransferManager`. - -### The ST-20 Interface - +ST-20 tokens must implement a verifyTransfer method which will be called when attempting to execute a transfer or transferFrom method. The verifyTransfer method will determine whether that transaction can be completed or not. The implementation of verifyTransfer can take many forms, but the default approach is a whitelist controlled by the GeneralTransferManager. +## The ST-20 Interface ``` contract IST20 { @@ -32,210 +35,144 @@ contract IST20 { function mint(address _investor, uint256 _amount) public returns (bool success); } ``` - - # The Polymath Core Architecture -The diagram below depicts a high-level view of the various modules, registries, and contracts implemented in Polymath Core: +The diagram below depicts a high-level view of the various modules, registries, and contracts implemented within Polymath Core 2.0.0: -![Polymath Core architecture](https://github.com/PolymathNetwork/polymath-core/blob/master/docs/images/PolymathCore.png) +![Polymath Core architecture](https://github.com/PolymathNetwork/polymath-core/blob/master/docs/images/Core%20Architecture%202.0.0%20%20Diagram.png) ## Components -### SecurityToken -`SecurityToken` is an implementation of the ST-20 protocol that allows the addition of different modules to control its behavior. Different modules can be attached to `SecurityToken`: -- [TransferManager modules](contracts/modules/TransferManager): These control the logic behind transfers and how they are allowed or disallowed. -By default, the ST (Security Token) gets a `GeneralTransferManager` module attached in order to determine if transfers should be allowed based on a whitelist approach. The `GeneralTransferManager` behaves differently depending who is trying to transfer the tokens. -a) In an offering setting (investors buying tokens from the issuer) the investor's address should be present on an internal whitelist managed by the issuer within the `GeneralTransferManager`. -b) In a peer to peer transfer, restrictions apply based on real-life lockups that are enforced on-chain. For example, if a particular holder has a 1-year sale restriction for the token, the transaction will fail until that year passes. -- [Security Token Offering (STO) modules](contracts/modules/STO): A `SecurityToken` can be attached to one (and only one) STO module that will dictate the logic of how those tokens will be sold/distributed. An STO is the equivalent to the Crowdsale contracts often found present in traditional ICOs. -- [Permission Manager modules](contracts/modules/PermissionManager): These modules manage permissions on different aspects of the issuance process. The issuer can use this module to manage permissions and designate administrators on his token. For example, the issuer might give a KYC firm permissions to add investors to the whitelist. -- [Checkpoint Modules](contracts/modules/Checkpoint): These modules allow the issuer to define checkpoints at which token balances and the total supply of a token can be consistently queried. This functionality is useful for dividend payment mechanisms and on-chain governance, both of which need to be able to determine token balances consistently as of a specified point in time. +### Polymath Registries -### TickerRegistry -The ticker registry manages the sign up process to the Polymath platform. Issuers can use this contract to register a token symbol (which are unique within the Polymath network). Token Symbol registrations have an expiration period (7 days by default) in which the issuer has to complete the process of deploying their SecurityToken. If they do not complete the process in time, their ticker symbol will be made available for someone else to register. +**Security Token Registry (STR)** - This registry tells us which tokens and tickers have been registered to it. This allows us to prevent people from reserving the same ticker as another issuer as well checking for inputs such as making sure it is a maximum of 10 characters and what the expiry date is on the respective ticker. Right now, if you reserve a ticker it last for 60 days. After it expires someone else can go ahead and reserve it or they you can re-register it. -### SecurityTokenRegistry -The security token registry keeps track of deployed STs on the Polymath Platform and uses the TickerRegistry to allow only registered symbols to be deployed. +With the **2.0.0 Core Release**, when you deploy a token you do it through the ST registry and it keeps a record of which tokens have been registered within it. -### ModuleRegistry -Modules allow custom add-in functionality in the issuance process and beyond. The module registry keeps track of modules added by Polymath or any other users. Modules can only be attached to STs if Polymath has previously verified them. If not, the only user able to utilize a module is its owner, and they should be using it "at their own risk". +**The Module Registry** - This registry keeps a record of all the different module factories. +**The Features Registry** - A registry of features that we may enable in the future but right now only Polymath has control of the features. Later, Polymath can easily turn access on and off. -# Stepping through an issuance with the CLI Tool -First, assure that you have [setup Polymath Core properly](#setup). +To be clear, each module has its own factory which is in charge of deploying an instance of that module for the issuers token. -The Polymath CLI (Command Line Interface) commands are operated from a *nix command prompt (unix or mac). +There are General factories which every token uses (if wanted). It works by sending the token to the factory where it asks for an instance of that said module and the token will add an instance of that module to itself. This allows for each token to have its unique modules associated with it. All of this is created through the factories and the module registry keeps a records of all the different modules factories that are registered. -It can be used in three differents ways: +As of now, Polymath is the only one that can add or register a module factory to the module registry. Polymath submits the modules to the registry, however, we are exploring different approaches to open up development to other parties such as potentially working with external developers to provide services to issuers through modules. -1. Connected to a full ethereum node: -You have to save your Parity account password to `$HOME/password.file` and run Parity with the following command to get started (make sure the node is fully synced before using the CLI tool): -```bash -parity --chain ropsten --rpcapi "eth,net,web3,personal,parity" --unlock YOUR_ETH_ACCOUNT --password $HOME/password.file -``` -2. Connected to a remote ethereum node: -You can access Ethereum via the Infura load-balanced nodes. You have to save your private key to `./privKey` file and run CLI command adding `--remote-node ` option. -```bash -node CLI/polymath-cli faucet --remote-node kovan -``` -3. Connected to a local private test network using `ganache-cli`. -You have to save the private key for the one of the accounts generated by ganache into `./privKeyLocal`. +**Polymath has 3 main registries** +1. Security Token Registry +2. Features Registry +3. Module Registry +The Polymath Registry holds the addresses of the 3 registries above. -## Poly Faucet +As of the **2.0.0 release**, we have built it out so that the Module and Security Token Registry are upgradeable. This means that down the road if there is something in the logic that we need to change, we can do that without having to re-deploy the whole thing again. All we need to do is update it. -If you are working on a local private network, you should run the faucet command to get Poly necessary to pay fees for the other commands. +### Modules -```bash -node CLI/polymath-cli faucet -``` +**Security Token (ST-20)**: The SecurityToken is an implementation of the ST-20 protocol that allows the addition of different modules to control its behavior. Different modules can be attached to a SecurityToken. -## Generating ST-20 token +We have a ST-20 token which is an Ethereum-based token implemented on top of the ERC-20 protocol that adds the ability for tokens to control transfers based on specific rules. ST-20 tokens rely on Transfer Managers to determine the ruleset the token should apply in order to allow or deny a transfer, be it between the issuer and investors, in a peer to peer exchange, or a transaction with an exchange. -The ST-20 Generator command is a wizard-like script that will guide technical users in the creation and deployment of an ST-20 token. +To simplify, it breaks down to having a base token that gives the issuer the ability to add functionality through modules. -1. Edit `CLI/commands/helpers/contract_addresses.js` to make sure scripts are pointing to the correct contract addresses -2. On the terminal, run the following command: -```bash -node CLI/polymath-cli st20generator -``` -3. Follow the text prompts: - * You will be asked for a token symbol. Enter a new symbol to register or a symbol you have already registered. - * Enter a token name (long name seen by investors) to complete the token registration process. The token will be deployed to the blockchain. - * (Optional) If you want to issue tokens to an address you own enter the address and then how many tokens you want to issue. If you want to issue tokens to a list of affiliates press `Y` and it will update a whitelist with them and then tokens will be issued. - Make sure the `whitelist_data.csv` and `multi_mint_data.csv` files are present in the data folder and fulfilled with the right information. - * Choose between Capped STO and USD Tiered STO. - * Configure the selected STO. Enter start and end times, the issuance type, and exchange rate. -4. Once the process is finished, you can run the `node CLI/polymath-cli st20generator` command again and enter the token symbol to see the STO's live-progress. - -## Whitelisting investors - -After starting the STO you can run a command to mass-update a whitelist of allowed/known investors. -Make sure the `whitelist_data.csv` file is present in the data folder. -The command takes 2 parameters: -- The token symbol for the STO you want to invest in -- (Optional) The size of each batch +###### Example -```bash -node CLI/polymath-cli whitelist TOKEN_SYMBOL [BATCH_SIZE] -``` +We have modules that can deal with transfer management. Restricting transfers through a whitelist or just restricting a transfer between addresses that could make an account go over a specified limit or you can limit the amount of a token holders or you can even limit transfers to prevent dumping of tokens by having a lockup period for token holders. -## Initial minting +#### The Polymath Modules +**TransferManager modules:** These control the logic behind transfers and how they are allowed or disallowed. By default, the ST (Security Token) gets a `GeneralTransferManager` module attached in order to determine if transfers should be allowed based on a whitelist approach. -Before starting the STO you can run a command to distribute tokens to previously whitelisted investors. -Make sure the `multi_mint_data` file is present in the data folder. -The command takes 2 parameters: -- The token symbol for the STO you want to invest in -- (Optional) The size of each batch +The `GeneralTransferManager` behaves differently depending who is trying to transfer the tokens. +a) In an offering setting (investors buying tokens from the issuer) the investor's address should be present on an internal whitelist managed by the issuer within the GeneralTransferManager. -```bash -node CLI/polymath-cli multi_mint TOKEN_SYMBOL [BATCH_SIZE] -``` +b) In a peer to peer transfer, restrictions apply based on real-life lockups that are enforced on-chain. For example, if a particular holder has a 1-year sale restriction for the token, the transaction will fail until that year passes. -## Investing in the STO +**Security Token Offering (STO) modules:** A SecurityToken can be attached to one (and only one) STO module that will dictate the logic of how those tokens will be sold/distributed. An STO is the equivalent to the Crowdsale contracts often found present in traditional ICOs. -You can run the investor_portal command to participate in any STO you have been whitelisted for. -You will be asked for an account, the token symbol and amount for the STO you want to invest in. +**Permission Manager modules:** These modules manage permissions on different aspects of the issuance process. The issuer can use this module to manage permissions and designate administrators on his token. For example, the issuer might give a KYC firm permissions to add investors to the whitelist. -```bash -node CLI/polymath-cli investor_portal -``` +**Checkpoint Modules** +These modules allow the issuer to define checkpoints at which token balances and the total supply of a token can be consistently queried. This functionality is useful for dividend payment mechanisms and on-chain governance, both of which need to be able to determine token balances consistently as of a specified point in time. -## Transferring tokens +**Burn Modules** +These modules allow issuers or investors to burn or redeem their tokens in exchange of another token which can be on chain or offchain. -You can run the transfer command to transfer ST tokens to another account (as long as both are whitelisted and have been cleared of any lockup periods). -- The token symbol of the ST you want to transfer -- The account that will receive the tokens -- How many tokens to send +With the Core **2.0.0 Release**, Polymath has also introduced the `USDTieredSTO`. This new STO module allows a security token to be issued in return for investment (security token offering) in various currencies (ETH, POLY & a USD stable coin). The price of tokens is denominated in USD and the STO allows multiple tiers with different price points to be defined. Discounts for investments made in POLY can also be defined. -```bash -node CLI/polymath-cli transfer TOKEN_SYMBOL ACCOUNT_TO AMOUNT -``` - -## Managing modules +## CLI and CLI Documentation Wiki: -You can run the module manager command to view all the modules attached to a token and their status. -You will be asked for a token symbol. +The CLI is for users that want to easily walkthrough all the details of an STO issuance. The CLI documentation is located on our [Github Wiki](https://github.com/PolymathNetwork/polymath-core/wiki). -```bash -node CLI/polymath-cli module_manager -``` +You can easily navigate through it with the sidebar directory in order to run the CLI and set up and test the following: -## Dividends manager +1. Prerequisite Instructions / Deploy and setup the Polymath contracts +2. Launch the CLI on Ganache +3. Use the Faucet to get POLY +4. Deploy a token + Launch a USDTieredSTO +5. Whitelist investors +6. Work with the Dividends module +7. Using other CLI features -You can run this command to create dividends and paid them out proportionally to token holder balances as of the time that the dividend was created, or at the time of a specified checkpoint that was created previously. You can choose between Ether or ERC20 dividens. - -```bash -node CLI/polymath-cli dividends_manager -``` # Setting up Polymath Core -### v2.0.0 KOVAN - -New Kovan PolyTokenFaucet: 0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792 - - ----------------------- Polymath Network Smart Contracts: ----------------------- - PolymathRegistry: 0x5b215a7d39ee305ad28da29bf2f0425c6c2a00b3 - SecurityTokenRegistry (Proxy): 0x91110c2f67e2881a8540417be9eadf5bc9f2f248 - ModuleRegistry (Proxy): 0xde6d19d7a68d453244227b6ccc5d8e6c2314627a - FeatureRegistry: 0x8967a7cfc4b455398be2356cd05cd43b7a39697e - - ETHOracle: 0xCE5551FC9d43E9D2CC255139169FC889352405C8 - POLYOracle: 0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C - - STFactory: 0x22f56100c6f18b656dbf1b156334206326fc672a - GeneralTransferManagerFactory: 0x650e9507e983077d6f822472a7dcc37626d55c7f - GeneralPermissionManagerFactory: 0xbf0bd6305b523ce055baa6dfaa9676d6b9e6090b - - CappedSTOFactory: 0xa4a24780b93a378eb25ec4bfbf93bc8e79d7eeeb - USDTieredSTOFactory: 0x9106d7fbbd2996ef787913876341d0070cbdfc95 - USDTieredSTOProxyFactory: 0xb004ff6893b95dc8a19b9e09b2920a44a609bae3 - - CountTransferManagerFactory: 0xc7cf0c1ddc85c18672951f9bfeb7163ecc8f0e2f - PercentageTransferManagerFactory: 0xfea5fcb254bcb4ada0f86903ff822d6372325cb1 - ManualApprovalTransferManagerFactory: 0x8e96e7199b9ba096d666033f058ebb0050786baf - EtherDividendCheckpointFactory: 0x18ae137fc6581e121f3d37ed85c423dbc3c9b964 - ERC20DividendCheckpointFactory: 0x8c724a1504643e02bb02b23cdd414da637872c80 - --------------------------------------------------------------------------------- - - - - ## Mainnet -### v1.3.0 (TORO Release) +### v2.0.0 | 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/0x6af2afad53cb334e62b90ddbdcf3a086f654c298) | + + +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 -### v1.3.0 (TORO Release) +### v2.0.0 +New Kovan PolyTokenFaucet: 0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792 | 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: diff --git a/audit reports/Polymath Core 2.0.0 Audit Report .pdf b/audit reports/Polymath Core 2.0.0 Audit Report .pdf new file mode 100644 index 0000000000000000000000000000000000000000..38821f1ad4181964938843d2b839911878fcd663 GIT binary patch literal 156875 zcmeFZWmH_twkX_$5E3l7O9z5$)3`>EkRXA^U7O(Unh*$12-bK4p@GJOdx9otaBbY( zUA|`ToxS&c=bn4UH{KcVy&tC-j8&_uR@L;HbFNy=_)Kwe&6pdOH02?*u`a!Uh+ z!MuW~af(0?7|5-9Gn$WA04O1WWoB!7GbQl2V}En{KrZ03l%S{pf=Ntv10nW9Ghetl`=XyXLDA;METYZn_^Cm;&%myTwp7ADSi zjzADE3NIkH28s|MAQ<(JB7>Z*shK;f0YyT-KN_HRKt2H!94bI=6+1g;Aei^}8wiS~ zz#CejW_10XP=fy}ak%BAfI4DkP$&p$!eeA=$|uANh6)Qpp}b&T0aK`;kueA?z%TKy zN9f(Kz{%Os%*Y1IJ;lV>)Nsb!(AdyW=pKFI{8wue{2%W3<*zWKQ-*;39oSOPn%AvV z{trzkMT5Kf2&A4XVus}fJPY77+?B(T55G320VMzUD&+nQAT^Gibi>*|rvAUcHF;@dZsr8!6a1aGzsuTFBWELPJM+IuKN$Qsf&6bJ4}y{e;Xefw#CIcO ze`B1X;SJY%Obv|;XU5xr-vJng0@%-DUz?$6N*N)wgQ{_vj{d%QTW+|H#LFwhsW&jWS+S zoKTPxOVWl~vEmmy8}AUOf5R`{#_GgrEO?H`hDlBi7+w~|{ztZ>EWlrOrFy85Kt7@02dbDk z*||8HpeTH!jneMUvJhvKy8d=2i&8b=--g|2qYP?|-Z_h z-eC1h9{yYA{$X}_!Tfyxg{?!n6Sh=>_&&!P8%}88Is^X<|Ey6DTceLYcF6#Y{*2XY zbjE5yl_>@X*O3o|2J|tt;O5!)Vqj_&XE9&#(34J#vCFH&+39zx#(`ZJ(^uXnhwrww zH9Jy%^hRE{%StCS_?`|P(lz*aoa}_S8C-P|*A=JEv@sE;_r|d>`xqQJU9gQ|Gj)61 zgAFP=?}D~P;h#ZrNtJ&uF;(7;yt~g`N0g*RG$%P-@9T?SD&cW_cKGdfpZM9y zZq$}+PxV=@*X8=`smlx-wbGwj_gQ5g|naHQW-f>_Onpt-VyeUGiFRIQR+jt@{eu zAdQb?wNO_bOW<66KV!_KX#1u7^Gw&O#h`U`_s7ADWC&NXMTA`{zI^+;I#y@f$Lue+ z<3bT#!~Tw@*J{fa^W1J}KRY>EjH*)_Uvj?mm${445kiQ2DWLFXB)KrWFMoU1xL+hS zrifYbjN=&Jq?L^&wqxBen5NWq6SrwBGEgcBV^MYK3~s+fnXOOYY@Vf9Q$q`(aOfIJ zv}`Tv9h7=l9+A6owr%~W`MB$e!-$rx2%{PEa6knKr;`ru^2JLMJ<4Facdr&MU<;J( zE63NF)^AKK0=N9i6!U(TeQ0dv3wF*^Fw_ne5?5oJ;=%PKVy;`&;6>ED6_U*ENr+}e zo5b3}%9(#D9b)SOum0R32Zs z-s0v14O{Epb|h8KIM-4szPnN#`t{b4Mp}@pl6_pg zOj&md7N7fQF^RXL4nO5y1+7+H%e@lHG>BHuys}$8Ge3BdRMAf@ROdwWmLs4y=wk;H zlIn?iA2p^~)C*6Z{^!b?cEWTvw@q_y-Qx8Hh`p8m9Lf3h(=8wTpV)(VD^x#cxx7te zmx2eeqOvfChE@1KjT1TvydDoFyp?bgaYt8YS0;z3J?K7w<>Tf(UY@59+{&~@_ptU87FI6 zJg?6-NSh>KxALWYqqSUk|J9a94IOaltud47j`(~@?bA?g&O=`k+PCC0)kX-*Cmce2 zA@K0*e&NC=`8+>^i?tUsE50%E=D?qtiqN(w_rQTK??r>6erDtmK73iZ?yz%5lWGCy zftGM?PN$P-XkWCs?dDNpTd_3*`-G=Qt#37F&5p>qVp@e&TwWAkWYm2;)DEja6+gzYO_}= z-oMWMYV({nx!hjqk|EYaCgk$AE}j2K^wVC0H3{THj8UgYJ~+iuXvaSjmi=qfp>M42 zjAa=zxvg^?R@iQyZBKq`J`Vi^FMv72vOK6j1*FkfkW8$N3t*JBl3*qyQz_?K_%itd zg8$Pfso*XfD>vu*LZria&_(16JZb8uV+)H}nYR^X&MOM}yd}D?!zVObRWAhb3ThtW z6;}{pV_PQ)96xYpcPU}roR8Nzw~<>l^>^R)I?r*4kW<4=J})=!y+1wti7*Q)BhyPA zPEriukBE{Uuk0KhQRkiC!*lN&Og2m!O_+Z#awLb&5KlpLmrd6ssPX>O58wQqROp)w z-)Nvk;2#S0IB(l@;np(qC9Bys2}v6~zzQ9)_##_M-x^=@Wghw!-xDHsnEGhechifR zSWCvqXy+YyIg+%~0?j~5q`37i)}z;kU6GWdL0-cPs?hMnqw%JCv-iY_-N|BxAr#UC8JzaX`FNx1Q%@~5l@ zltPkkH7e!IN#cz!8U9a)_OpQ+Fn*nA@S4nz?{_hiu*LlqC6tCuClp@pU{O##D|IUu z$7j-UsU5YHxTSN|V{WR1J)&t{Wp|oi1s`|^akuqAI4N`x@N?io+`n_Uiiyj)&5d8Q z?A0+wdNuKECIYzjy8N@H!$a9^wY>Fm9d)}tHON0L_~ft)8dmksSPVMK zO|@KF!N5Rv{M;`t{80=*7uB36w^SCX_?;fwnoXFsery^3(F~8p_|&UNOBSON|H}H7 z{`M{Ed=(CJNiy8}A6&1?eP`0$?geEA38Nbec?vHF(^7OQoeIVfc(^>L`2r#)o zeRuV}wS;C~*k$pq{bsRJykz!X^UlVLXd=~(LJY3BIU&c@!(_Qs18`YnL7bA;F%nfw;qxmuW*smMP0qgmC_$kqvJ z=V)`|+5Pg{q@Jq&3I?Bb=4b`iSk3!-W`YjA>ockD=&=#T1Kv-wPo65@aVR0Ce;xg;Z)f*< z9Dsw4!h`^w03Znn`|85-3!DF3|3iWQP~hK10p=;Jsc{MH!|w;{HC%Z>dmF&Eu}h=`Z8~_^|+#bnbjS9I;?cdYXH_+JaL;j zc851HxkblTVb&=zxv*aMi#-+|$J(TXg_nklZv5QeKYr`jvNVW(9J7sKXG4c^wxDK5 z5ZjX7g4vWk-q_TTg-R-rNDN((9I|8%Dt^CvXU+d#!u4+&@K4a&Mcc_eD%vT^RSLcz zs8sG3=<|Y2`~?a$nyK|=CDm&{)0vG`o`SHG16eic(h~UHU1s-$s@xwM6rh9i3$c~m zSLvD4v$sNy7}ppB^%+42UKe~(gdt}>SNMQpWys_U$~t|M&GQRxYHy{1t)eH*Et%b0 zJq@3)0TBnJv)<}HJFAc-wd}i_5CH*gksCveyzQ@NM`kh3War9!|gu%QOa_1(?9r+N6+wv6T zGdDov)a7xuEsc)zct9z)*hzHd2P}ugEVG{tdx(F(16*An#m&zM%_}l5Wr4$nq1L?* zg#&=7$3%3fFv~T=NVm1VgDE$4;p`a*>#kO1P`&Ji^gsZ5vlk{%}Oen2bpfJk6s%s4zH+gWuu?ET3X`os&tu6fVLc zw-Pc$DCa~5KLU}RM31&hqg1dp;%mEPP@KT;+ubF89&gvDR$H-_#GaAUZ-HQz3*nV8 z1OU+8Vm8wJQf5Wg**ZY5Izh@;Ywj%Uggut)d?F9yYMvsqLq>kvhV`g z)o8@>-#0TEIyN8GSZ37Z6fz~{rZO>CbGP^daHo{MBp$iEO;Lx$&Vyj?h*!xs3+-kq zm>5utnd^X37hE}~dU)&f@rF98Vn;kD2T0W5HIJjSQFzjM;}H==wT?B-Y>apjdFEsw zYZ$ZLs3-?$k=6}~5!y|0;bN-0k;>!iiq`n|S`)IRvc7)@i zE1VTBy3gey3;^8OW*!r}1_(E~46DVOfZT2Q`i3|rl5&TI=MBjD0&)-Q$G5vDJC6uG zr#9V|w#?4&$)NDg&NCFKNb^bU7Sr_1dKWq-p3x*zmGX|ioaSsNfnKbJnTIc6$XU&{ zI->@fl=;EfMDE>t6n_6xLHh>{cPu}9hWyhqvi@n3%w%&d#?VAl#}w0Y{Q?gr!Ij9* zt7}mwesbl?2%h~qMTe%LD@mAJ3AZwL_>0LGk&D@#13H_8$Al+R_0o#$@j3%K+l0p? z5(Fqa6uAgL7(SQEyxdf5$npz2pjmkFda7l8P2;5Tu^4W>m;(6x8bG)`v(`Ntb^b*{ zp^h4yQp@noMx9%*ZM4Z~zQ8ASylmL7Vj*}raYvSokWLN+YaUmswQ7tyhS@|noroNh zD77oliR()-rY;LddPL-rCC}T+S*Xf7BT~g zuq<43A|6lx<#+Y+J?Y=dbMf%)Sv>Lf^$08v?Pb5}_x$Xz+I*Y~7q03<<~4TD1__eH z_9bmIbFK}xsuxGAv*p0H258%Vs18Ule(3_a7L(&Bf(gK+_D6_X-S)WwBJl20_BiLa zE#hD3)PJ^#=x3;YJtd}OR#p>O{nnrGsff>!JDvx%ObA~w(8~rF01&BpP zB1+Al1xG;5PPW`ww3o(jwQ(0bc$gvWZdDn#CW@t|5yU~@>% zMVb#n1O|5#U>Vej7qx8${hR~A!bU`Tl9qTXn0zAge0mfw+BtfC-b#(ITbIL9>&L|S zAqvQhj>AazOacX8i+C|R29qV{h)-YL*9Vp$AYWYu_WA@HXfITQehO2p({3{DSw^@5 zk?KkLP-**2adi-Boq*(hbE0>JdF#@spS)kv8(@;Ynf*cR?5yXj z0mp0NEEwAmpPi$walGgQBS+$CZ}C!rfX_bUCU!1a?SQeDC<&$C@!QOd_d;%e$fbFx zfB&+~vDd49PmR9db6{TA)zRGLQX^lE=Lyu$%fWZwAW2m`wJCXceXm zaFz%nA{dA)VHum?>Cnvd$yAfC*&ganiHl^pwQ)=2`HT)CEn~H6w0g{O7M1LkWUig& zMG#mwIBCWb9(D+!lYtFyFEKB-dnsT*ne zW4s=)?X4i~aXyzw5l&F3l^E3#9@sduS8Q6%SsHQGNOhi=W>wk!s}5n8%gw!^qeYeA zQB7L1TlaH?R^y#f5sN&s;8NqH>}Sd4tswBcj4su=o{~cCQdZ8a^yt!y{QzD@nMoq|i@cw4_9{tW3i*!1f#k*V%N~<} zyvauSi;Yei^hHs zBsf_!k6%00M2|m$-e)w;fUr7=Q8Xv#*mua4d$QD#uMi25R-S^TGS1d~{GYaGz%8Gd zg3ZjCMqU43LCm7nL3EAxpOM*2Q)0`a$4hgoT91Jtx}B>JbGR1uAwAS}2Dq2fx#cP5 zSB{0s+{)~vBzhq$dkkNp63dkxwJr56`7BL2A^KvZCR<+Kc?&NlRg2Ln^QFq7?!wM4 z8(tE>cr%s1zGi^hk8R&-&(0wo^j)1bcdis1^z-K{I|8uxL_O-$f>6=q;;)!RK@cp& zgpZGle}mAyfB+JZr~_XC$A`Xo66iWWI)%9_|#k}m8b+e*)h~s z2N622Z5a|0dGS2Rm{TG7m{aXoRgJGV)Y(9dZ2Y-Md>=Ia8bC(kn$GChGom^;0vJO7 zb1yLd@@s?e*FO}TzHiFC5Erzrgn6&vFfPE|+#W`ihp{w|1| zGF#~^w=gj()Kcmmd%#c+)4sj)`mrlFZrG^J$5K%KkbmQ6cjFM) z$$^U6Mz77GZVXT5$%$9&sYM)-O1~xG)&IUpexckHR??M_HMH`=?ptH|;K4+LrFJB- zUZiO~SJ4yA_5$0`8T8-8`T&v3>7G=-E4qFw^Pr^>Vskfc zs@7|OoN?Z04`}hchm1x2Rqht!kVcTakNz|_mLx>#vdAwmp5zPT8k>m*2589rQkv-K z@`_YSgFGQ8ot9B-0}qWEP571;$~UmnWudMXLHu1#iwBObU9Lnjcp&Y zdXu9U5HA91G=yarTho<3tXa*6e_Hc=?-WvGvA+>7JJin2*r zub|jC-aWojfvZ<4ClJR7cc(qEh^-xMlXek;dZYlQr`^6+zMd{u>3a|$lkj& zsofP}3>_N_Fm_mHMG3!#9-q7y`COM(C-qDq;JSIn_v`4%k?%Ry&xdFBFvWd{_ zdLl3mlY_eYN={k@mH8<;$=RSEc(~d68UQqI)Q(yzZ#44~J@sO}+?(E)=s0rQJA#}q zHZE22`rU0|ODG5$yL!~>TTa)VGforJ>+0B@Ts@`dg=u>TQK-p-9YLr|sXtVu|24%^ z?}z*0rQjc5w0S4nF~bVOrJdA-ybdOlOv0#3Klg;ds}sMyy@N_e-|Dls-1PFwo;+YN zwEwsPVO?$1fJg>tSWO@$mOnj355zQ1R8lyrfn8cTtAC|p1K?%5q?Wk4!6)_$-z036 zR&ezkO!&I|G;wnIWZwI`j5Y}2RPk8{S)OsBDJ zyVQ)wz4OFsa7kRHyQ5$zD;PG+EH^ObPDf{;5PhNBdF*}-P)_Pwm~9xD9NC+~JW@-y z+Oj&eLqBIj_7=gvUvZh8*ZJif9*ohob~U<19WwK$Jx7*n@pq?EyhkMGo<`@9LDR}2<1TtWI znyVHEpP3$C^R$`fXVV?y8MM#XaAI6_@gyw7ru(%;KCdFZe7FUup_3O|4K5d7%j{`D z5E=8=+ln5_ruro6tt6=)`$WSJoVL9){7zOJ@aBC=3lB=Sy({-rgiTE5C65d-@OK1N)laIm}?=nwT|6luoZ0+p~YYTDd1_ubyEX0WVTA0S5)A*{=esin^qE0|LD(+oR|>ER`pP^A%&>z%`&<)q7=;ZO5j$dvi|1Nx`@cYtu=5 z6Po1v0p)FL<&QUH$C+5ASz3>1d`MKrn46%wwD}^8JiP`4zHT)5fK1O9R;|I+J;oj>B~_{?9v zWISkHC!^}OtPud9&4sI1WaoUI7KnpKOcQD*F1WU4zVnY(lMdw~kD^>;w86j3qRQp4 zYwOrlvRzLNj;(DOOI!buY|=q(LrQr;{9n~isO%H~@K0lWOCe=f;SUEj_4hO|qW;W` z=wkbRa0BS!gf~RyMl~y+j95f*G@axueK%SrD^KL2WzedPD3wXubii)w*p}+g)>$k< z*ojKQw)ElYjKu9-b4ZE(qQkbGqtL1?lfu5Uas^2+%z_Gt21LQ~Ps=@n09zw+g~sZ@ z!U6`0x7D_=?IHPAhh2yYi><4uP-^;kN)dmAdzH??h_0+yUtyeVWFkyj8TJkPYp{@l z*^sd-7(F6`$^2eeaNais=Ps+oQ14vVp$=~Cj73C7t;+xjMAb=NiLdP3{DX3t7iZ!k zf0xvpbvK`y*x(3tS#M}gh|_>jN)g+mQB$Gs-=Oh@Y9c!6Mh4ZA*8r*FT>-9H2SNLj zP_|0XAt&1!wg{%A3};w6)zU^K%I_l?s1x4Sh9A}xXq2@PepWpu5srX$&mGp-!;&(% z1}K$PuZZ31N8||4b@=;QCcSmRNTNq(PLY&?5S>*?hfLV;iHL z12xCP@i`K1QN4)pc9HMwt(MUAp%#2z z-SmPdo2(AoU7Kx~$Nh!tTI8Xcg4!t}>y_aQSV+xO!v-(D+bLdT$!xkZQNv*tv@oH z5v+)+kbd*p&)FMFm=~c1o+AQXo9D}rqHcM5%izhT3T$+*fbQJHHBmV|&{PoyiI0$p z5@z!Fo(*HY2=O(bfN~YYLQ^`H@@31ZOxRV=IHa&n;f!;YW;IRgn4UkK(6(vEvsA%B zs6Mk=PcqEv9&vBHRXVTSs1I_1ibfUL$)Q^tfk@-j%$L@+N^;A5794#1fXGpV8LwXc zxI8i&G$rHb8(KBk#$+RP4REB7$|$RC8}AZm-{@hc^Q8epb48y?36R;nq>8*k{9bRtuQcIg&m z!Y5;R8)MALIXdrw$iq3u?Ual7y1|7pGij#sP#$hti-1g?PLMl$$h}w+Ej_6&rT3&3gBf?xxFEw@?2XA1(-Fkqdnq;h&wjfd%Ig1R?0H29hI)h={iKPc-|~6Zf@E*nBzeFb8y3Bg}Ej z;s%r)xeVuW_gWp6OxkZqzsXn?bqC9DctnqF?xl#{%t(xGn@#FP|EsjhubK#_sThF_FEnXg>Ht&yjasU{MV~VX` zYy-`I23pQiP0%-lSS@Sm#ct>@t*HClb)<5rNy)Ybk9C7iHhhu?Y?F0gfMv;^yKE1D zkw)?@N=f~>^qrnxt&bPwM-B_F0iO;kt7wu!hL=oI)M!?!Z6yK}O&PE{N~kGZU5}{H z6U|4Houq{dx#)27E!r{?himG8q%vFsC|nX1mnuZLYZW?n1WU>XI%!-yEu&~apOqpB zN%CBahgmA2p`2QkN~B2^!SE!D$OTzPVnkir0}vkAhaynebrW2(RLH4OAVUk=?sky| z)5<08vd$UJqE*7YuK`r%3?1Ck8+Y)kt33~i3IuIeKRcM$61VhnyF$JCSUfx#@IwH4 z=x}7ZHD}7|k&loQSF)>5afMU%*uhL{;DB;>;YN|jYGs2;*8E>}xOxmk1zi(6}n z-}dk6U+MC4YL;5+AD(*pZ%d-IktAR5boiqz*uOLCkr7DvA~uqRJXkEyn)ID>q_!0$ z2(3VsS8w>0%F?n&GmxZj`9CLp#rD9HkR_Qi_s=ctGw#w2!GQ+^L{i!e6`cxIaf4%ki zulFhW1%JjbDoa0t{&ZyG>~$|^HWV>!c7$}fOhQ^lGw(av4hS&85)&hYT|(@q{(?z8 zbdG^gp8Z)V@fNx{!&a%-luyTI`%i0o(a6yYeh0NRFpjS5%v6g7(OLBK$?rVDf|#Y1 zrKxpI^U%p2Y|d-It6Ke(6dxv*Z2hachDF};gu*^(x0~${vCeO=LzC!*p_(3CN(rX! zl=dDncs)e8^6M?-ib=h`=4s~5EWLhIUO_+hIAoqCOvCF&sAM6v#ESJ#1}{gb>cP~} zG^-=^g-#-iqU=z+@RVkOwt35uh>%9T)sZU%+}9N-sCu(C{SSpS&z?$+Vyj&_VUEix zs^g$kReo>CYKLuCwglyuHpL9)xlKTVM=!IRq4D%q<#c0noKmYpoV{XRbpy2IfgK%A z)Lb_4vn8iK<90?4#L}HE?XJwrJ3NIc&->U=2a6bt)|*V0EqNy(Lb_6|LLC-S$8N$I zjgEyDJLfsl-n%dz@=3-GF0LW6;^UkoE}cUD&|Fx*v6{J;Xi@7%8q=0hT%QwBw1#?# zsux@F*%huY-l4v}zE_`yoKzEU2n+^GWujqHD=Qy|Cu^=j7ePPBSkH^-e7Ylh=t66o z)ew`jt!?%KLgRe;*^*tpKj^R%XLdnERz$Yu_2AE^jL9TzNxPX!E+kRfVve~{TbaGb z*MO0pku#NWRE#(lyiIWpaF=rrAHfI=Nghph08NGrd%s@>`ydK8`L#P&lbw4XBJ;ND zlqVhML$3iLy0zqR(EXr_fv5DyT1mXgqFFbVA7?NT&?>BD=-?n_Np>mJjK z?N0`8b*AMGvCDoCoxU29kuDipJn@Pq-x$yV5r~zIUx?H>Z20Z%u;qQ8!W*0uXtvnZ z$~r-WK`zs12Yc$D5BhX@)$L1ABnXTrIbe19bKFQ2x+r~@t?B77I&Z18AlJ-xpKlWT z62bz(7MzYrZ}n{_u$q7%Vr-l(ZBxC(NvV}jDHZ*0lCc|a$#B(UGcduBqplD58lcd@ zb|s&LO30O#UhQ*q=U#1+F0VF~VeQQdYkAdP1IE6?JtMV}hs3`l!kjOKolbl2vL8+$ z!jl;)EgKdm)mDox%33^rK6;f!5kGBl6vaR8-R4j|%vGnb$p>ftki<~00Q!MHcx&e7 z*wB{=NXkY9uY)j?K%KanqlQeh8X4+MkogCnDfj26vUfRbYFM)czi$}iDQfSGz^6~4 zZ2KSkh~yQQ)D_$B;)Ehh@)m_tN!)VQTx8o-C5G(Iq0UFbu1?_DN=u0ntw0a^lzb@n zTUwNlsI}leQ98L+X;HZ}FVvkm4ewhLK$OOfHk-MwU5GFsbO+9d9A#rv<(XK5Wy}s* zrfWkQ9j}-+-RyL44vTca5s1X)#Kh%hHyDf@()X%gr$S;XKvyq_={{#Ep^%7HfF^fq!phuvxKb9~-uM+jf>dOk-!Bvn$f5 zHt)rn>M}QwEgJUQ*%fT`4CGb+W$>mVnee(|-5TGBlJZ)rQbZfv;=F*lamwkFgt2?8 zeZbm@RYgOad%a3XwtnM?f{D`UD{2Db7Hd;9Ab^=8+b=D9(OrygbXs-Yi%)C*@G8ZY z6GXW>cq*Le_Y1ZMdc=vbf1(o8>iu8~^?~6K!PY$7x8PP#sCO$Z+U9moN(+-#MLa0K5^YZqoN-?~J$oi7*yfp;Y~oO_lzZ5Hw(Y<_ z64r(=SMaLacuXKK)AooEa0`NLIBIA*avCgB_B=kfEOODWUGsAx_>oQMg*>7?a7#UM zi=Qb@`|R>gM=!a~wtB73#zcW{4w4~600+nXaUO_eYs8DrNK{;3V~yLup=ihtaX6x~ z9BQH<6mwF4wNB?r_48b$!yd-1BGO#2eP}DGd#Ep10vk|d6miNlqBIfa1-u7P>BV(l zJ{}jV022Lgq~QT2E130oGx(D1 z>cJ($AJ>PsZ(5VB+@_D7mTCn-jwFXK-7IYm_3P(%#Y9|$MmmBXg9xYq_iks``fU0H zZY<~OXB=)H4e77dyA58gF~lf7Jg!|SmTFO)^Eo$`l)eT8`#t+rkwd$CBZ4mW?-0Jr zP-F2)-$wN&l>Bt9g{)*6mhPQ(Xt6a(LYIeJHs8Rk@`wxwOYVhGU+4nx!`ReV4>a zJ*D&=!VeF&?Ka;|T^B=fyUqKvfjkp^4>ztAL13-)I+;c2O10Fwf@&{cOG5$+e33-i z5rzoOe4dNo4~aZLaBT`EByQ-fG!K!OIEJnb*Kw*@@VTvJc*V>trAL^%zOZt%$@|*I z%+%WFYRq2^Ei!Q(d4uqnM=qr;RIkA;w3%6!ZI9^^pmCF}8{Ol)lWGutMcS&w64evF z#mv@x_Xl@vn3`;udek%!9*XqIe5eh%TuHTDf|g&T#r+^|fQXC#tnYWI4emO9X7vXGL1CS=RpR-gHO%f!OP&NvGN5cNK99@YGm zbax@jM#YWj)rGcd4@{;=E1$T?dezekFD`wZ(%;(`FRNFlO||zB=eLp}OM#uxWWP|k2LtlC2h)jwC?6bF1j<8qEjn?pb&^Rxl_|ThjAZ4L z%4Y9<)BDBS+v;_`|n!6XqDFW`r1#aS+v zs=aWiQ{yfyRCdaYl=27?B}+73Z-tU4kESR%6=>LL@DE7{n_#y{S^MAi|MwE^KePRZ z0{@}FzncR0ugCuJOUj#HF!}W*<*$z+|I2UV{Qg}d2=&_>yfR1|7b5n3 zLY~JxK*N!Kyg(pLz)p()@>}FbdNw)e*0?znf&0Z}+I0Q4*R1pO$!q{9DjX&;RPVTlIe?};0U)NxWR6O7HwfTtMCYT# z24b{NI$f{0LHTvje{M7TZz0LWSay%xlI}G18*EoPm$o$mBoVd23bD7}pOXkI)R8jkvHH&Hw&7gnat#A)bSO zd~E=LqDP{o5`9* zz2FQSUD6B27?qXi?+LcmWV&PF)$+st$VL-AUy0-kNO*5@hh&lcRkE&R{2B_9(7-iKy-yR;lF1BZ>1r+@76 z5S|%bD?~$g!@l5fKH_L?;2PPL+qpCEWUqH_Xu$u(q}bO$icB|ww?*7oY}Bu2rdrdD z7Z@90#%-AR?G}ud8-1C}RArFhu!Pe<6;JR=!H6MVE67_sDwbicg?tUzsYMJszEct7 z{}T8CUx9#(fQo@Jo3#Nch$oTlqgIj8gU@A5Qpi(YTud+mk6vft-=hSs$Ez2!2-`GS{W zJ*51}O$hqwKD&jV=38gnj$PdcrN-Vasyou(le&loLs+`&jS4BgL;}qKQ#tv)1(_~& zIoT#gL={^3ELc^IQY$Oz5hC{T+vl(KxS$Zs zkLASv@fSRWO4Q>XgBbGL+&=f-jq+-CN#gm*bbJi=#lens;0Z63N)GbrgYalPDvNU7 z!*z6y=|Zx-a4A#Nx65i;k~QlHRDFGRY)ed*Q5AGTv$!HmxSE+&+`D(>FF;uWq%WFX zKioSd6^n9~OZA?j&nB{sRzemyda%bGla_6}c!thv>I(W9(FH~j38;(;8=0?lOh32F zF;J|`pvD&UzI8|XP((Pi);`=o+J$bDr||fzy=I^AMTW7PJGk_%AUiMUg7pbjWAJ{O za$`2>+oye(Wy(l>N;ym$qy(GUx0W37iH8%(2DA4(=xBgZN(H0$O0z6=-O66?xsS-Y z;Gc%fr+p2JUbZr1?O}M$Ddp4R++z5R$b%DLZES$=Mejv;%5juo#*>gLmlv}xPLisF!)~XkG6YC_$$D4Un^5bCd$fGp9hWLKw&HYsL#_2vGhDXi_eA(sEK8|)N%$+f09|H4Jd32jkGl8kncVaXFLrKCsJ1+& z8%sYS7?!&<0+w4ziZP1fdgTzvRz4Z)HqoaXO{6^Jxuql+qLR>XZh?JfPD+MTq-Ydo# zh?jfCTr$lF6S#jUi00O& zryA8OzPnhJx+b^K?EUJ^ImY8LC;B95U^`u?vBho2B-SS(?-C8;Q_?W#eiq1wIkF%9 z^zp_EpGODA@CV$s4Pv_R860Yyv4Fn)bRi_xooAREyifk>`x~Ka}Q$9tb%cDR1p@VQMXK{-OXE*JGN<+I_XK?#!O`v^}k?jxkO|7>H^gtTyV z6ms_Utqa9h^dq%sdz$O^oiGc*g$cbXxR5?UgGHUt@R`GK#4cSMb1$SU>`;p0if<^JXA$oSXO~WB zS%`od&E>Z$<7Fi(zg}tYh`vw18{0~9D|C$KnJ~>r5gJ^yq+4fhREcRCeg1mD{fg+j z-1qk$u2e6WrS&s1TKy*x$j4P z6GKaTw@6Ugre=q#wl?x?8(h;ab6;WNyiu)?p(Xmx>-s{s5BpgDw!*iP@kNmr7;E#) z$_WG+`ML)8J8zpJrGFxM6hBHd3Xj{h;CkCUI0^OXICWWvRB}}o-jC$|IxUUUR6nQp z{n0p?MXiW7_q4K?Lrm9kk6{Z(dIP_0`I!ILN>Fg)V%8ONi; zZSu4?t8}vXa4~{m*~^aG@)J}Ad7%{}f+~$?3jXUX$|G(vYZ`Xa;q5!z!CK^3w^ps5 zX&9Z-6;FwMmZd)}e+rVIaloIKG`^sfLJQIWMm!xSCkQAuyo|fmM0Z;0v~sMGZlnUlpm(^VFTpKyLO6^D)10mD3BR^O8~SN7ghX4W&Bw34>ehRtJx}q*xz&!c?0AxU$zi0e=X`l4E^n-L& zp;II(T#D9;K8gv7iHZ`%Ly858RfdtUy zxm&w)-EG|+-ILt2-J9Gmy0?2IPmIUvN%r_XO+EcQLp)Dt2!^{nb8)lXK3Ylhe6)&3f)3D<?9}1b>!R|$hl7$)N^hga_$lK z94Fksd-EZD1z*Y6@QwT>Ud2D<-$_B~fb^bpCCWLEBA_V#N6uYwmO0nEb?z8*{NSSl)|AKS*^_*MbTkqRi z&$;8sxlfUEt?M~A%0K=)B6E&h;nf5=ms;HlITxtzP~EwDK=lLF<<*Z=*VGKDZHt^M z6Pycwje_}PIF=r#udwv+8Tt-tgb^k3F>)W7K&I5J$M`rQv!S$5YN%1DAqHo{127%# zfw9mX+SYtgbEf9Knzw7t*L+ZOQk1M&U9+lYd(8&C9Z#FJm%eSY5gzrNgj{yvPoj6l13zWn^GFQ=UwfA0SC`@e2{{*iN=&#gSW^6bX5 zO90NkAnKlrKU;DZE%Vuovw^c&XH(8}KGW$;?wOo3EzV?}$vD&KO!Aq;GqGpL>7P&k zc>2537f*jBYMp-L^r6$Qp2l8I|LgSgr+1$2bh`cNcBfNLC!hA5cG?fyuiL*gy^5aR ztI8LY&nll$KCN7%T&-NCd`r1Qxk0%O_pk32Z6!RNvJpaeNsF7`Q_ycBxG8>xS?l6# zB>Xo&tS4HUf6jRXu@*g|p1cn)Mmqe)Ts{ObI)eY|hvy6MKG9gu|85+&)b#U)_2HEN zwxs62%;|npl)-Z_59YHWuoAw31@H(gfoEY0Y(f{I9N9V-9)~ON3oL`DU=bXFGjJK! z!dCbVeub;B5w^pd@CNLF;V=SLz(_a_qu?041@FS!@D7}SZ(%gN4=3S0cnQY9&+sUG z1RubMD68MYkFXfV!#J1#6H$8ah4nBAN?2z7P6IWBiqRi@)FvtAlXGKNG1FUACq#jgzP4J$X@a? zsUmt}Ap6LEVk9PFCKfmkUy>LSOAe5OB#v0gQt}FUl^i06$!p{Yi6=JL2|>1 zd`Lb*51|2RNE(q;xBwT)$8ZYH!DsL}oQAXT34B2=lPlyG+^c>izmcot8u^3#N&X_& zNgAmpHKdk=NMqc`fD%e6qnt`qL6uZR)l@^8P%YI_JvC4xHBmFQ&=?v^n$kFGCFvxC z##0+jpmv%_9W;qLsf)VlQtF|}q#4PiUXn#qsE_(-1KN-_qNy~EE~1MilVqls*&H^P z&1VbQVz!JeXOFWd*=qJI?wrrFEo>Xx!FIA;Y!BPVUSY4Xf3dgN3Dnj1*~jcN_67Tr zU1Z<0OYAcHh5kZ+rN7au^mlrV{z3nwf6?o-n$|E4(=r|IE(9mFi9gR@;4kvcd<);o zxAEF{xa?}`}ls`rw{U1_^bR7Kg?g_NBHafDE}9KgCFB> z^0)YL{x*MypWyHEll(pYKL3D!$UovA^Hcm2+@(I_pYzlF4F7_k<>&Z${w4p4f6XuO zi~Jk@E&q;x&wt=Q@}Kx6{xiSKukc^^ulzTDmH$q@CKvcM{s;e)|HZHKYS;x8w47wa z9@q=7LLK%;(`T zk_XF4J2IU-iu=Xm3jjdpD*N# z_+nnpm++;027iJt-c)U0e9->Saa5b{l>%@ zQ2|i*qL@&;(Ob+8W-=}*lq$7GtJ52dCbK0bHqIJvORy(8lAJELC)u0g^EYVNC^fBd zlcwnz%`&sHo407$DyMau+&kLl1=_Xm(6LkJE_Zglt6TRTJ$vQ%?$ftl{{aIF3J2Xi zxM;}G;$bj+#K=*j$BZ2}e!@Ky@0~QcWJ>AOY18kUasLAk&Ybno?6Nrz&z(1a!NNt0 z%a<%&_Q>)Tk3RPJ6Hl&uYSrpBPe1eQ+I8zUY<;>igWT`E z^UfwB?j42+!){0@4!SX^^UY;~?qa!^`{t4XEIIm?l7UFcKz&JKa_2&Blg92&UU%?B zN3Xkz4C-Bg;bk4Yh3?=bIov}IuaLuf40}9S!QII=wxc^pirt-pou`j2?^N6oo7<(; zbntcOfbAS zO*hgza@gR4ARAUF`Y@+qza4||4_vVQ9mU2i9SRoSn48GTJK4s$MYOzpp*y&~cfpOh z9&s-$#5S-l^>r>T?~Gk9MJ9IZ>&D*b{KA4DnU7t%#Z1JkBJ&&N?Ico)$Gd}SZ+q|9 z^6|yEH1_f!^ts*&}O3*~+8uS^KI6K>9F(s-B2 z9AWG(gE1P=>2C~-s?U={a&Zyr)~BAcM2yJW6$K*b9^uB36nJq?t;B6qD<~h)3X9=S zA;DU~k+>q`g6a;%<)+pmUDOXsKJ*dGe@EM1?7j5U%_+m8DGHzIcMw4#C-tI+`E}u7 zT3RqQRfveP1Fk8Kv8^0$-lXyLD(dx4Ho1`?`yd~AJFKvEIXEuFHw*FLKK2a_XxWdr^{i%cs7$pvqtW&uFs7bQ;?_NUZ-& z_NYjHx4zzPy$2PzJCzqldE2euO|eLRtNOfXC>YbBfF;ssh$b>Q7lm?gePIzP&;_{< z|0!gl9$BSSp;XE##N9b)D!wyvFVuKE|HDdE;VYt+O#ZGG9cHj~+RgDcH^pxnp01qX zfVrP`>o=&pTys+%idv+@u2FB&-}?hZldkDBSje^uebtpo}ag8^h&2T=g!FOn3E z-c&F#8ZN{iA)QSccSb{3Uf$X3?p$76KCCKSHr(qrdCT|FBlJl5RaVza%l( zd1)c?YAk8pq@5RxEFLZ+!UzT~yr(02A%-HBBi11laygMQ2{9XS2ysQu39$Hz$Fc%d zNS4T?a{N7+a&%ZEI=D!VRt_wT&>p=bv}4yuvDT4d&9WoOP1{FkgT@hR@nx0?s?ld2 zZf8Z;{XGPQ$#^I9C>RL=7p!M-5JXU>h^7RXr832zx$Y3-fbIYz=$5*|hZ(8Rn={*K zXqa9G3%Kad^im{;UaB;hGuO4di+%+=5r+_reudYU^h=mc&!Ywy@t%iRhd6{diMWhV z(DQhm!|N1DRbVMFvC}JJr5aKdINx#6miJlSqB;Q3i4?*b}yqoB0oYrZ)8|mj5 z`ka1_L;J9zWlrWkIgpkf4Y+*KKzw2}V6kRa(GM#AYUHY-Ust-*T!<3AWlIBB7n$8sOWnY*i98Z zS>bQ*YGU8`G9pyNKHu7F<+vu zRi;>6;dW+v2-)MpdpaTy(F-vYu^geGhiG!eNS6g0IRM91fFdzrof8&wb(?+W-k zpp3c2&ENVC4B>5^d!3&K{3};uRNVZJJcc20^Uqs~A#w9RFb6~8=D%k;hQ!T3ay*8_ z%|B=;hQ!U^s~?8&Rz=sooYKJ6veyLSZfB(TA(!q$F5QP*x(_(LPh9X97h`+6A~h8` zwkD9)DAiTApOhUWWqnB5Mp8D4ls!bs=8&>nQZ|H?rI9iRDRYvt04X~_S|KaSNMQF( z(VT#dlpQB!J4jh6Df5#uA1O;AWp2_kP(?izU9)7;NhX!;gkB-Nqiv=U$LK+hdQhxA zsP>2Oei9LuV*xDWPL32#a0;4SnVJ`gH*K9csokCQb*%V0F2n0^4#9DOUPm!{9UFNa z8!+NM4>1&R7;za9Mkug!G7fyXd^h4f9g&9^ikOYKj8MqKxs0GNDLTZR^1#xggYG3_ z^mV+F@$yhlAj#w~rJ3$z%N@k%B)yzrCv6EaB`G7k^_F?L)r>T<#=;&s07Uh2i=A=v%)a|s~Ic& zja~bRLDbso`pa>_^}VBtV(>f10oNz)Do!d~A7je4y{?ZOi(PM}SE(@NpudVB+3%K% z?sK$q?KmzMor4)`DqIfpo*;upAV#o2f(oklOW=o0RmhOo2a;pXT`#<5fz2I zAQ;2C(QbX)lWxJoBcR)Gcko(YZxzwt1}b^mlc1#=bnDkX*eb1Cl``BX*fOnKP?>*s z!7f4`Da6zuT~tMI_p2gdku*P1xT^br5cB+HiGntqzpStjY}V;{wmeH)b57@u|8Ogg z-qZg6vE39-3a;$dw;;GRsW6x+0^y{>Zo$WeFS`%V&sREi+=oYLB!vb0SX=UIr#>Q` zwe46~*sY2TkjsIa{DS3BVt$d!shr>z<-o0SM#`;;l=ESIESDk(mQ$<2Cztc7)p9vb zM7dq1DV;j*N=cE+#JizXE>jxszOl@4AC~d?jKf^Fp@4hI%-I^-h6 z4i349gV^OF1O6_O9xbxCzQ|&^Cr17*Jae*NDRC0l{B9e8gBmhm8srdPj8(j_`JL?`kvnAF>CF>^9zx zyI^pqeg(S*2S#r7Ns487L?Hgl_cOKQ=znw1)bgcQ8WepqF(iWbeF{T zP+Eu+EG22Aw5|<#*boVWm~S1XPK$=3e3%-gky==#w2mG1KUfD%m9!rc5O(QBNZ@|3 z0ffIrd?#pVT=+YYFDU&13s*$}uo-rcaj*jp!4Yx=#FM>!up5NO(-EG5neYTG#9eF< zrYwd&cuAQ41W5?*hIH6~``89Jfn^86L$DvL#1{S@X2X2;A=a7?dPs(LkPnk!8R;IL z27}=op9?LaJKPJCNm;lc{7Cq*@FsX3_OUm^wV(w%jKJ$e_-E6iu2hG?~=nT zR68e>Cm4-fY6Ll$GYMXWWAGmFlGo@YNhf7W0qKG8M-U6mpg)fGMXdP^`GY=$*KGC% z?;LIq2IR}5g4^&f_>$O3I_X6Q&_;9;UCX9`3VUpZ*GL$L{9c8vpGB$JOLg=ldya48 z)rzFh`LF?3#1Buyv+x?x<4oP8lsrsMk*{e7I+Q+5zhY1DE&K!JFr4)emY8~i~m zq!sB+?j~c&OtO$XN>-B-%SzZQyggohc`2VOEs&Ndz6%wEj)vY3 z{SnR#FM!@C4|8zzPr_Q9**-W4pW$^5z9JIQ5(8f1sc(PsAYKoVWn`oL40<>A@*eq$ ze2+WO@1&aI#!3}5Q9NbE%S)%AL-_=KhMvUhJ^B;4x!Tm)vmppA3at!Pgm#C&gg9J7+$``2 zm5ZYvhSzvp@0BQVJK;m3L*Cg*Drrl)BWH$^@uY;zKu*phYsmBR*k2+CkxQSD%Q$8| zb;x6GN}JR6v=?4O=qOr(zSm=PH$6qKGbPh9Ba36HtP3k*qu5k-KU>Ly>>c(6`-)v- zHF$-&hP!w&_wzK~g%9P^_*(ug|5h3-y)9i-XcQ9_3lvp~U(ktZtISvSRu(CjEB7it zQWcA*sIUiKzVTHDInU;>PHYc6LbG@Ro><;Rc^(QQSr3YmN;i{5bQal7Q=}P+Hna`t z30LrF{{(%5uA|pz8`gt#BYk1K_)S&uqlo3=H@|cF>u`x5#JRnTEzeNs$V2q9LI)K@ z{=I4PFP6d6*xT?qJ4cj!1Dxg>5>GDC7g;_^!7IG2Q~)0K47|ij$Sl}HI{|2_RZCHh zdy=ha7y6M*@+S+U*V_}Ns3rRv=E4N}DO^H5UIb5(k$en10$F4xdo{iqwaUMGcq* z3!o%C2kw^&_y=SRFfssq{5)E>nJklgkj_S{G8k>zUexaWXb0M{9++Z7$?1-A(H||u z8oXAao!}@z<50&3q7{1=b}RbPDi|Xf2wEKg{&uJj3<|#htHWd9-tc441nt4X@JwuR zGhBq_u$jycJqVNW28P?b~Ow~|MUXR@@MSfPIefwLOtoOaA!6d=X(x%hhGf4hz7=n?}1)$ z5S~{`Fie>i?ckn&2Z{X$3_^U4Trao*?*WLnkE{>k2+sX18pnrFj@|@NIRMmm;mWVV zef|Rg9j5EA02s3oEB+m(ha)h5g~uG+vtseU9{V#u+ziA|0P*b+p90wCMPSFc{V@PX zPk^M608XUNKO=DO21xFV*bm^H4v?}Qz`r5_@v`wBf#Yfz1W26%koE#V<97g>VtP8x zA)_NeGi)<+GeA~%fNZSLA{Fs2K+76{96U6%#$llEli{A|!!Yb)~(thkt3)A)ig#WBe_GL>| z;Xeb({zlnag+?g>Cm=}*?aykJiZKdGRj$UUE>lx=RrqiqPH)UspCydvQWDUcvq^%k zHi)JS>SS5+S zawYVAkKNS0kd+QVF)l2b2G-ao1a}OH(Yz| zlIa?@o|}gZB}K$f&Dkwmw9HZ{@rpAMa_-4@dki`_=l%wFc+*H)sP{qgCo%l|d2RK3 zh2<*`yb^MS+_&_vYe*ZKs9IwpU{Q+^Xx1?zMqq?>Y>3g|GEl>I%Rl!Y;{|he13z9_ z)_7~2iPp|RPA1>c;DI>@2lY4^>P^m*FAwfpSw854>e|nL4*eQZVeeZ*XUSYR0UGGJ zM}xw(O;JVi1AfACDJ2?`3mVEW0*Y43*1cdTOoG|49yz{VyI~cM;%d>=3#LoBe#m68 zn3qhoGP9dyWFf0#70L!JTD07IB7b0JP78M8M9C6=kAz`&W54Z46&+6}qC7VaBuu80 z8SO!OV3%H?c4;yeNZ^x~35mH-Wcmiudt7Rk0VO!e=AO8Av=OP=vqwn4e!MNj(KGM` zY*Y+3H!{SXz}I8`dM=OhT9GUTkwNW0apHvhMN9ZwnuC02(03oO@Y#yk99k7V8*s)1|4+4RU`e^fx!GWH$N?{Gb~VCTH@0c<(fboG)cvIYyKrfEg9Oh?69q@~4? zEJC)d2o)qqKV6R%TGc=NEjLStah;Q3&u)b~!Q`k4U#XyO?W^JQU`1FE#_;*TaIRQL z7ikw6-!e#QrPf9}#dMFmE1^STznH;sgA@8BPEbzJj)=J@ZbCwF;{EhK#dPfh#)XPi z%9WgNiVxfFzw8Zgxj0UX*2=dmR+ zo6=CCib~Q1vjn?HQ3(`5EAc}RF(ylktW2xbg2JWnCO7cMn5piq1Sh;dYL>Mdg}5OGM0@0 zdE5fA7Uz&b)yNwSlm^^PSd0mLHeF6vtN3)8DZV(5za?^{MT_RyxV*9=DZr76&X7AiME312~MO#|6VEnkHvAaD#yfowZgwZ1( zUJ?54)N5ff*S30L@Zp&oV%O3cvqn5TZ=QS4u`v}Rhd$HP`N|`QL%)B6BNl&g%!K=( z2J~<>(85xn8>?HR+oF3*Cv|7t^-pkSLD>SGf+;19mMKA})9a5j9?KYKdZ0QzSF!{2 z0I1N>SRc@cKdho8Ab3YX!_tMgEw>N!blJyN;kZZZ-oE&*4Uf48^qu?2hM&zCR`H&v%uO&xc z75*ro&B|fPO>!7dO3D?V^%Np!u}mOV7trSD%JOq`0e_Az*@3i4j{Mw(;iLw!zyRHz6vn2)bg7OlLS>ccFp1qup%fZw5%$fS3}#bHp|2$N2ClK{N?YTu69%;FKb*EZ zIA(Y4eecctGIZhD#oz7tqPAtPM|w`#wDG|Qw(`D)@fkfb+WvfIL~-bk56Uk+M7oig zWXo%tkJNlow6(Bm?W&zS#hx+@wbm-Vh&nqtU^uEL9RE=jSEEJ>bDu#8SL^hp=v<3w z_mT}fqjsaJRQ)6LB16eg%JPs*BC~OWO)x~I1bytHlH49wFZDEC6T6-8PK52xG3P`K zy^sdHbz(IDd|-}B9(!#_-zxNuqM z+Gn4Iu01+@!Gy8%7mpsZsCCyBedlc6@$l>ySz@DAv7*-tWe;!N9Q76xWRD{iUJYcows*G%ymwm%dPlQ+tP|~HybsuC zIhWd(IM-OW*bmx&uzusd=8n0;y4JeG%33!Xsh|yn`SK!fZ63G6-O$;~FjUwo2kMkW zKFp7(*=}K>T>D85Xi>||w^*mfLictH)ic+#)*LWX^NO@%w{DP^ZZt-9Dh5TuXP0eH zTiQIkflw}_fV{PsWhc^4WDds3tew2WI&)axS@|tUivtt)))3_z%P&3nz%LuOe@@?i ze(H>hEi-3rAbm{_+}nNjr;~NI0TYPo({seMCiFF)X1)zozI2FXKfU+pGfRbrQNW`s zS-}1BnYmTK%_UGM)l`woSuRm(4&_HBXVXGM@GaxJT|bx z6DMk3#Nz{nLE?YZz|(^hl3`vT9akce&a}@=q{Ho_66plpFasTgZXs=9=xCsc2`VKA zQv14L zj_bLBX*Ftzb9CZV3Z+tqVU1)f+?!#yQV9~i@l#=zy=O_6&&Q@^3s|X2b^L2-n=X7j^j_5?(WK^D1(%H%~B~?Cd zJoQOrc@q%$&xT8EPcWg-+VXPkm+~&i+`S}@aJY3YY-&r3`o(B9a~7J89yJ_2x=@Nx zWO=uswr{tfv-hBa-Q37j%KhlmL-!LoOkvP@Q(JDs^_T{ z-_NA&}lMph`+<2*8QGb8rmW4FWfh3 z$O~Bw4wjACRosmAF!mwC&oB+EYZo; zCcp76@Vf~ic2~ULts<%f=ZL|P{k4bKT#I_tITjH;OiL>g$7M2w#4ETrIR&|6NkJ8i zSNerQ(zsZQuyK6%kvl@KU%V9hB`Q@4m89Y-u1K)iZB(Jv=rno_Q^Z+gtua=nNM!LI zVlm*&rgC_QRb%!*S{lwZ6@TUsSxDlo@m6%4D2j;BlNmiSqF3cvOa9t6=%K=?r9B^b z^u+woE|T-;^UXT-c

>J3{YB`{R|9gQtaL><_NI^cs( z1Dz6M6XR%c12RMvLo6&M1w58`>I3YZDB_(4hK`b&5Pt(-iW@B`bvGzRFL6p)1JWSL z@754af`7!_byC~IRD`0?1BW0S;iw~&o-0Qqr`a6gA);t>cYdWP?vH2=tb zo>mJ9ee|I#ZE4#(^I5$_n4|DGA5Vx=smC3qIE|@f0hkvNz7s;H=*t% z%Q7`qoHtSBW8$(obE-A#HScMtMxs=!LS=9(m5QP=J<(HbWI^Qz+E^Cl%B?4EJgOAy zC+m5eLR(r<2_AE0iHZ9idG!BD7(n2=)3RG|3sEHhbjxSGwMm z?Uq(ZJ0+9_+*_B!dI$nf$Ae@(oP#SMS=^Yo0=wJDPZi3h0ngSIWw^5z6_!lNtu3ls zCvj*Of|_MMbVTe{I9A-Dq&|X!WPYF-OKzE?QnzlPX|8CY>7p6P7O+p4a=PX-_L+t? zl$P>xX)FIhC22Tm&QEdiUf_H{ZSiC?x45C{t<>dML~13*RZ+?XO_J&1N{dybpAFoR zfIazqcc|0}33s4`s5NSpMq-@1B~7d(VGI{dflh=%qXCI>LX}z-s5Fdf3Ggb~I$+F@ z$a*O#9hS~ZT)Imo(zF>$;zsu%sAS42x*(v{x}(Npv+OINH(PQ^c!WZHbH&o;<_e(3 z2tPqQIYVlbpJXUird(An`UN)h3lh;U*atlPX{$ncTd4abseoCXj5BGRki!L%6LWCQ z&hE8h(3+zV6V+OBRLQY9JP?~BCcejq!ML0oe#NO!s1zxgQUoQqP-1b2hu}Y@dF2uM zDN)w0rVodq_SzMcvPSfi+Lvlp(QkeT$-mPn{EJliZAn%@M<`0Z1S+@ip6H7KgOakS z`BL1lWqeZM<@Wf#+AD}S&wgU^U0#F#SJrkK0m<`mZilvDvK3%s!_oj}ibzOB` zjjR#(=^Gmg*xh`(euiP8UZtgyDo5YK(2I6s9hCu94}E)sW))q{Rw`GjHnSI%3JWzF z3>gx|g{3N;UY{YUFsRb?G4>$=bOTl5Zxm|vdV|3PDm5*(lv$`{Kiv#^(yT&qtExz| zfJUd*xC6S`TB6-g2cW;I#T;6N&Z8O+k8a~+6ERiM0WZ6yVyR4GQWf1?X%_mNAYNz` z<=SxSvVVwSdwt|W5qgVxx$--!y339}q>zS%vt+LkNwW<2+dX^*bm3}Hg-@aXd`k8X zy9ITa*H9J_efZB^28~FKJ_Gw`uP4XQ*dsp&+uJh7kl9iW?rDOl(Pv$0h3H@6>dRX% zvBtM(Njzv@h?kgGkrZ-whBcu%8A_xBp#eKX1=9ZNUmv|Q|7lipy)%Eix;Z~z?H00t zhkD5+?`l8nvS@|nXpRO>C46wD3KdC(M+T-+b4t}p6=!aRLMn1=iCdemE!IxfmT4ue z3b#AiH0rQsbl-~@lr-5MmRzkjh!%0sMn9T2jWCD^ZP={}bk0FDaCmR$991AQ63om| zqKXK=Y;OVvGb2Hf>W#dd(Ry=~hFC<5h+o|sgTbUoFbRWkBKYU7dYy@CpS%$jq6iaV zjEVV~V~p-URue+@%;B?+_$7 zZPIz$?$F*tCqw%;ze$olIZYDp|NhZ;L!Z#&WFmR?Na*=9=R)iEyh#SV8u}x2l4O&_ zN}_!{bP*zcB(KHw*MkiP2AYpDPl%=6Ox@f2wy1lv zd7;J9euHJy-iZf7wYA$BSvq_0+&DdsbOTB%9vyI;$)tP0Xwe#orG;aVYqV;ji(9I~ zUsYP{*+{QcCO617i+EClY*UmPqZIQ$txWPq^0B-rN=1I46azlPU5>lleYJxf6CG33 zGYt0|=W7-jpVDtJRvEuDd}}lrbUL@$7;82g%|@Ntl1M#vt43iloAf%#rdC_y?Fr8K zcGokTUrbGCMB{NF`$~*6LQR`NEU=4;K(uIreaEVA?h`w z@P^|ZI`A=G)|BGvc;%InA8UCw(DI}2JaGKO9u50<4_`gf|K5R3Jl(z|8|JU<`P6fv z3~7I_H}8MuRFW^H=d@4>X*O?ZE3LA28p~>Vf0wcHTfM>IZ~2et$7Vn%@XQD{f|s(X zockIyXE}}ztgEtnQYTl(l+F$MvO?wHq=5|=#~2#w{V6nsHSo1CW_vsOI;9VC5AgQ) z-J>0^pI{grJIZ#y_5u9^##yFmDW$#ztX#WTUv6Axnx8V)_n3aAab=v-mtxRsB@dp8 z5>-kCXH-FaDan|I&U<2$Gd+F_@mu=II@_$?k-l)rbn^*NybeNK6|aME&BTL)$U$0u09F#y(n+&2qvxWO z2J+)Y`F&9IY#0|CZ{_jwYA8_K{exfD4}Ejiq^*7P2e%2`(|g>QhkkwHxxW@j`;9xc z1UKZgBA*qMJ+Pqq*<+#KR+CRm_bwaQzO-YfG2ZxLX)T`{HR-jHg z0%NXf@9K!o3(+;zUMTv;B)|91tNWm&xj4_zm{1Zg4<$akwcexfU^`vI#;hAz9|A0d0!rJ@N}wntE5;wN1#XTrcx}WlA2KId$$I?l~F1( zimJruwGDIfRisR{LWOZc0(u%~m@|};<#ZjTRHT^QQockp&_h{)ZtE3ELN8@erM7r; z#7ij=Z?pw$rpN~f_Jm8e$VUh_Ji&^1BC+UgRDcoL_DhA@LIgo)tt$L;WuVQpO0~*J8AlgSp+sJ3v^t$y zZ!j8lu`w2l_`B1#xTQL^g7VPr|5db5&||!rEGMY^&S5ll#Vm6b}sKx^WMLTV?Sj=Wn+2iBwrgm!5 z8{DA7dmJJF66w9yEgt_QBvg?lyP`JRp3tKfJ;GXhLanW5r%@fhskhv99-%PX(NCG` zo*(wO(LcPIpe0^tFdaRLx7?$3p&M_wHbz_i{>9-}j*-Pjq6)km->Qeoj{C8ranxP}vd+`{^cpE&*eOqaX z7e}^l0|pH61iUeEQ;YrACZF;?4Rpo;Z-_UGpEpvaYSImSEE%g9t39jW5@$@IQmPdS zwSuYL8f~mbqg614nz<=KT_OsdRzc8c5p5Ms2&gq0HKS<43{}(?Q0vrv0-7>B%2$y+ z0likMa|7$si!PTnYEK0bcFeX{Z#d!+T9kH8STZ!-5%P_&Wa!*q%{51saADIl73z>A zR!RgGif6zkymbr4BdZ90zs*75z}tH8on!sHWqcUH@%Jp`U*&+bYP8}HwL zM8jkLTeHlxP3_x15l?=n_Ctu{tJ;_8MAjqJdFIU06=Y{kWv%#c#lv5Q#-UmL5fAQm zJiXcW5Vn+*0?26hjm2;#)%F9)4J?Q6b+--j|MGo#KF&wTe&3rU9clTX^l2 z7!e+Kz-~>*&L{bd23S5&CjR1&iBPf-168zd1zEtVXmKS?;3fM=y8J24)yS?_i<^LK zW@WF0cv%*C|Iu%M!7gpW!@Mi}9e41y&=6XZq`)I;y*f2PZ%=KcPff-1UtG(?)~Q`n zi}XdQ2O1ttIN9)nxGx&2I$DV<-epT`oSL1( za~gN$cQziNDoh)#8kaU*w@~+%?l1jcY37#M2EtA0DcSLvo><$^Mw1%RMvinto?*FR zogr+H)){shE*qG^;9&7pbZfwBdotGHP(r5$noI}NHX3Fc20l+p6}>xPY7h{giMah4 z{+)iw-z-Nk%H{NCXXG5tq3d%aZ*8DiaZ5XG;1Z^f{FJuXp*lLUAmfE zd-0;!i7wQAGJ?4!k;iOxUyX3Vy?!R% z0yH2 z+jc8Z~+wZ+`0yQo_{2jZ5Qg4S7fi7wtaXC7~bcpX8(>K02ra1m-`ZQak-(=ck*QxXg zn(=fT8!t`MP1cv`U(oGQ@73(l>8!d1y00lSBo8%CGR`(KBN4*dHA8-aR}7P31+0hj za0Oixqfv|QoW-G4+8kW#FcM>mAvqC8k)lm=p|QigtE(d}<)o6hlzB?3Y?hdPRQBLX z#4Fn=(LaN^4~+|MAeW|Gy)>oniLf~*-GmNp(S0rqrKtD!*QSq(yI=N~vkvL}1 znv5t}TBR9Kw3ybGMZjk^`b?(x%*134n2XJ2W^SHpNjaoEsXV6)E4koZFC|kZIJ5Jk zg4IJj8kE0v&AlLdn*x7}mQZR>bD`9z)e(k?2X!}oJkV;?(b*qQ8~@SV;+5%@weIcH zra!;=!5JGCtX*3D+&aR_d$*&8>z%3Po#U^)@%cMPk!Rgd8=WXwamcf?fsrn7#L@n& zNGekI*N$Qnq)F;gT9pY*#6%ldK9jD;Ub8EkSz0GFbF{Pcu(xycwhT__;}~X{XdmX7 zp_mbOjb5{vz)Fnz`1pLQaIcxwVO(KaZ=xm>PjqOMAOufMo{T}^iVx^zpS!{TYVAwF z<0!6#tGavonx2`SLv!eC9V5w>EZLH5d4xe@d|`|wY|9QZ7I-`wNn_6;&5R@q44CCG zB!oER&tgdOV~%ia4t&V?0D_YcHUYAj4I~?~fb(GzLqg)s@AwaKG}>3yJ)`K1UG=K!UG-kq>zUbY`z+W}TtSu)e{CB%2g`_MtiToSR<%Y5*351zAeo_y4XdY4 zb*Uq;=8iN_4}Ho=6j(GhvdGwL*Pj~TkyK9D^hX{pp_01oxRPe-@a%QR8h>~6gY56I z>)+qRR{WRK@_{?T_e{OTtWg$jxO>M_c!THBNn8Q8K*9Cdcd{R=+SA8|@R#pgGW0lE z6`im=?S!b*gANAET@tqWntgM9LEo_NE6P_bPg%rbOTA^E@3@cik=fN3SG1Lh7FMy9 z%D9MWa5*`aNAg21?3#84Igg)1EOQ^G&%zGQTS!;epj=wfwj26-)a!c=A48Ss9F`Gr zIbg9QE{3`Yoc53UbeDtVWd`i}zKct>^OC@eu%xJxqXgM`TM2H!4YO~(6*qujrCROP z^IOSIKgbp6AyLC3lJ|Dtp@*Esw~bx3sbpcx+NH0(#y)t@$hNlSpK*LmUcPzDJ%1Sh z8M-{XhW!v^h~$)<32ru-*uIFnTwaod}WR1T32Irz`Ve9rFpq)gK&*`$oyyd zk44s|>c+ausxPa%s&04V-bP_T<$_tAjmyo;E0@jcsqC2*6~dL_S(_VoHojGNy7G6` zzpt}<+_=4rjjURLl;%Zvm^u`Az|q` zk`;H#$VEA&M}i|@#XMx2lCGU~dJ+oJOwW9X3hDY=nAz`iR{tb5a z>&IVs_4_Y9g2|vwBwdB7F@c?kyEJD{mG2R$eK=77+vukq4%?qJ}q<{qwO89I zRrn(NuF0E^k9~X9q5wZ<=}*Wb7_bu|;%0OF%aT z`?{sw(q3twbXE{C^H4(dTCEeiz7-JdLiwa&EXPk(@zY})zeovc{I2~E3%cu}#1uSDd=|#8=E*L!%k0AKs2Vj(8A5E94`)afs z>W5rE&TolduV*1;4c=cu#hDRn+pfk~??UwfIUq^JdJ;Lxr(jJ2C#b8ogjtW_QV@SQ z+TqNdS@;#l+e*LaiN@VchkicZfh0SB9Q@79+TqAs*yd)RrwYz_&UE@eIcXQLN=tjZxqR1d8>u2(e!M8tm49unX+}?&PlL zYF&|A-bN_3Q`HVPl$R~}!Xp+Bg;x9={7&Yu>HWp+mgBp!3*f|i3{+`Ir<6uW-(hjs zwr4joq>>&i$u6-#7V~vWHgFLVqE`r1f~A@hg2ablOZrpCsjW+njpbZjG{PogCTMEE zSyZ10n-X6eoLq+0?TjL^_=Bcx-SXFjdpJA67vQ1C)NR38%7CX(nbJj?G1RbpT?>2U^s}msg3;G>#QS)k)9FgpsQOQ57scuZ| zkT0MWKTAP545>sm{`JRt7sV$B!~kgf>}pA5{QA#SL>(oqS+!Jss(xrOg&8e?iiG4X zi+AB^u1mp^32>lo&Vz63;eE08h050Z+4}>~e=3;_`B^<;`BK~7=wJ42zj&uv#qoMi zFXue5s=wgs`CME2n)1Keto6N(RN`Y>iPr;a-a1>(TO7KVJ&||{d&m2*I>mg>N<0ml znE?ToEpw0c9PnD;x;kc_H*smlt;^Hjv5BWq9o94|sf@rJ^m9s0WlX4|++or+UF%%! zob}q8^w2129e5LN(TLN~t!{o;`E8wu z3*Ijd3`v2I3@88-4b$SU(}|7h>3-X$Y}xnUqnoIGGXlzVoS- zjh8Mf-a}XglA#_8?ZLiuf^3k}=+`5(-SZk2;H8YPu?#I7dtUck(`aKl#S^42*?8_?cRq}HXnezdOKpt4mWyxeA{HSTalUenrbhyGLanRKE2CSjxL zq~-)?DKzh0BcwBBxoXj8i+~bxF_V?h9;waj);2SP7H7F?g!=-w?P7Rw*2!l3DVX?m zSAVtZPL#Nl8=aB!bD6>NB7Nh*?Dg%W<|3VKhW~LFS=;qCG06wwsS_XFK<=+gNhz`m zbGn&B1e}7#U(UEng$M5T5eV5$N z@c}^;FTLXPTFh#r)2_qn&)Q6Av62rj&K>J5)8msB0! zH`3MiiS~_9v6?gY0$Y*OlcgnWH}4a%C6-um37PX zs_d%9c%QBe4H!$-iSCo{jqi79ml9L6>C~fI%9rKc-Phyx*m1c(u`4{Pes#|f&DV?x z9eWfA)+iUB5mTsE%_3RtX=HZnk4qcGA9v++S-ROoZU7( z#8b@>K^g1v5B3&&L)P4#ZNW_y!REeBlXqw(jV5L=iv@;JR&lCEm7Z)j+S8L@x5Sm> zUNz;kmX8v!el7j(+RVTP-XQ7^C@Nb^<=&L}VtUX4E>07bgmYERmGH~u4c^HjR04|K z@&PhVd-B%-laf|0P!$y|6bIDyffpAf>2`aP^1+&-XmC9Kad_r}qn9CCcBBdukPZ)K zx;7P+)m8y*wgMj_UX{0Ezmd%IRz3P$U;dThvoC&tVu%iOx~#8Z7dD>W`5rk5F*j?M z&P*v=zx{8x`BYoatJBwo1)K7*1*yvJ@08?L*Xp#gTJyGp5rLZx8LQ1osmUxynTrG5 zOjh2c`SVY*j4l#`P&R8fB^l zRn`t}soXUYQza%@VFm|e4O;sM)s3E^KY|Vip#0He7_{Qi>DKu2s9=2du?jkrhM>KL zUG>6I|Na&Hiq9e5dpVoU8A}BA;_{)2x%OtXyi1pbyPn$Ysoy$mk>}<^Ci-;I^!oNktoCc6VA)5s>;?%T&lh+_++k$az zo65U$NkcSueCZ;%FmS)NL3njUly4xT7rsg}Fll$Sy6fFJGpNDd+3XO+wI;9tK!pRc zmX0SwtMQM!VCrBW*RKlx-o5`0Q)VdDq+x|w=OS63+%vM5glY(L<#Es8`B1G3Gfouo zgH%(K0--=aMaGh@&*s|cx}LXP=C)`dU#V(;Nf@t{)kV6=$u+&s0LcxLyYxHm` zs7(he)oovAD*JMKK0sYvnKfo~T`nu~`#&nmE#<`~p3c~xsvYxyCund^I?Nv$vyFd_iTerwbO> zO;@Wiji0&2iV#w*y=)4Uz#p+K{y-nfaHFlb<^b@J9J^0IxZYIG9W>d zeoCr{T|*ZQYSnq$MwYPxn2baohrr0N{(wMa8`ojW_$$UyPU;B3`%@?_T-Jnj($1N3 zH0gviH%;|Pq)%b_l@61vBs)T{(y8~nC7V%+4;t5mhBj?;Fa z4(eCc+^dU+fc4NH;a~4vxjp!{;z8MXKQNp70V+Deyr5*cDj$?9I!qSxDA69a?<51a z^|HBX!cI0BhhvZ9pBG-;mCw!9fpPzSfvndfu*(w=IPOsS&;;;?vimsp<^hV~i3Jji zq_W*dN|3e=;sMAILG7T2KuvKRB`-;0Id-S{SC@vqVUaWQWqw>)}QhYTaa?=QX8l?F%I_{0u(;lbjiOu8-x)EdN=r


( zV%o;TL~OeMgB=4G{MRwdJq(wA>^De}-tb|l4ZL;bJ)nGW_7xc0=4b4y@b&MLz^22Z z!*|pYEYE~}Z!6)eM6RWD1L!NuQ2ZNKad!dKP6}9Eo zHMZhanqK+cR9yHRGcbh&`dKMswH@n5|M_P9%;|!Rep4nirphu#J0t6c_urlphRS>i z+K>{|MjqnO)@AM;4Ae}cuetQH+=xG)bcBgixZ7a>DW7|{;nZikNvhaCA8Svv zkmNVPWbu>&HpQIXM4hMX0Zi>Z_T)eDR}z009n4YS^C7AeogGiEO362v-g@R0@k%A* zzm5j?wie@t)0}FUl`&#e66C1{uBFt3)f@^~p!vPshLQs^;>cdBD~8i4ThUA-kGgKE zl~}pgS zf1=m*Yo4*#_cDW)1_C*+Okb|={zF@~beFJmZ=mFF|81s8>N+(SF1!fCgLV0Ah~%?mchBt1|-CcV;` z>T-FaX@ElhP`?q5Y|>da#hk0p9pz)`&pi>IeR7ei*K%X2_mLDQFXeLuz5=92xKpB0 zz544`%&j}R357a1m3a|5^Swrqbgt+LV6lxKUuW@#dl4_LasxzFJqQ66>{1lmnC^`i zF+n)?Bg^Hzg`aCWfgy$9o)mpqrL~RLLfbibRM(2p>~PnsGryu>zkA%;+F^PN7ki^2 z@SmQ9g>=)}MEh$Aq_FiG!>A?uXMZvErH0tM27<>2@7mp+hrzpB^~`@klfa$u5aE z^ak-Jg?GekJhHgiJ!OpmY^XMpZxA?sXV6js8w5?9NUua5qK18ua6F1)(s!y4xL^Ms zoD7+fr4Qve4om~9iqQ#llguEV{*L4)9|=k&rCT+sO5nouLiPf)ay&!eej0->+MZ3a zz~Y`_y2O++JYt61owOhDr=!!PtL&ZEz4T@=T44}GzM78p>_#~1k?^oNOsLVmTKoVr zo0^F5x3

Jt0DV{5RITIGs!-q3LHf2rDDkq4T@F1pn`C($s|G@4ulaUwnRE0IX{DFh2FjpCmn{5|aDIF0y&f>xrD z^oDC9;_4JD0z*;@V@b6#NB6!e_emgKFXaQZ(t>+Eg-ej1gT&4c1EgnqxlM3yb6!yCqZ&{%cXtokr~#Tkn4}ZbEU{I46GeeBK;_*MiY%$KN2k}rBJV4$5b5K~n zUBAbaGZhs@6?&rD`8qehPV(dcv#1VPKh!K~peEp51T+??6K2Av>53LQb*{%b%LL4Y z5_%6y^JfwzM`mB_4|nLm2NX40lpgh&)E^2pM<;*)vN?vx+%M>S`Ye`56mQQt#9+0+ zdg(rLqoswp-))jW(lLY-u?tvONke%)$ox_k9%nzuN>0AUSeg)ShUUzA8VHG)>M7O=0~WG)ypXbw?`)B6#lcx4$x_hmy?@Ctm8D$Jtr7Mw#2 zHduvj$SKeq$&4fy7=)wSVU@Owg$+0>n6IL@2%kOx8u&jHS2Be>C^3|hcV>IO0lKkD zTSB5YNQJfu2MZrF$)gn4Q3CPw+JK}t<8Ii!DESKE{i;KFY|_G{g&;L1#e^bn35AFe zb1z0kB3y?;m6}j`8$Q!VEEZGAYrs-g{=ly#lC{SL%nnhwbF%1kVT&&XPnN-D=HxXD z-0jjyVOghzxAr(MhX^}xG3fVo(0vVI{&a`3KI z6B4LVfi^Z%d96|U!b!pjDjiN{$-z2?ABtnms1?i-&k`x4fR-gQMT+hDE@KOOzs~-2 zc3il4nQS`?p+uuMhatdn)T1e{f!#uGn%>%(5zH{X$fQ#WE=fNNTDCzT z%1x|f|Er`H3raW4iRgar)$uhKAM%c+wAGR(LKCKE@m}mw9H@M3b1$DIP`k99?0Dwx z7hlP0g9=jQH;torva3hQUw^u)k!LVqlJabncw?@iz7kv$$>Y-N^I4&3k6;cS6pau#0WXto4TG;0^Ol zFPm-23qovUv0IGd48xCX=<;o9=dtUFj6$Y&67-%Pd71nI89COmX0`gm^4H_Lu8YdD zCoo)%`r~~hrgb%??sF~V4C~h%UUtABrwwWqJ>bIXu9^%gzcqJdl%J8op1luB?Nj3H6DspPpX%<6s*Nk{yDf@5Dyh8eADjGXGMDUTTjllJNGh5w`aV9A}HqOy}+6>_L4Mzeue1Z7V@sKQ$8Mi^S(H}I%h{= z^o#^kIl}J_doPu<9Abw4nTdR2AFZDwH|M$C#kzt`rn}x3>^&Gj5`nej0HHF52hlJ= z69V7}uZ#qj!8H$hmi0T}X;1sR7sBy6A%%0S7OIF&w?C@sZSKj1ZYofDi&uh~^A3?6 z3DqGeX^}%VC0U-j>(V}|&|9i&F_tth30_#4r|z4P z!Xf0GmG&f*oMlrS_i?h%RACEOh#QN12L0@`Wmb5=dD@xt!K9L(U!gHG)vNt9`i7}V6;1NQyabb*~;*W13Nym~c5llB{ z%!eBtkl9#}Cwp|GWI;CG=rFcUN-AnjhB9ZPLrmj>fTxk!I8c|?!p6m!C~9twcP3#$ z1L!448xuJMkg((z3(Y}J6oP2_k>KJ=Gh0R~&C5%}2vy6Y*p4KYhp{qaA&?dTqR{Z5 ziv{;#nZ?Zt_M1{Lp-GwB*z!psnkXI_vmzeF2I8GL(X)N<1$eO0i zi3*~{n1trIfs4m|7c%HB7k^#)OIGxnTRuEej+HNhD%K6baLG$xxw8 z4(ubDA!7$n7K<949e;&LgwoSvMFNSBLT`^I&Pg!O^JUD;m6tFf*NYR9LOLxJrHWJH z$;@GuAF=Xd2i%2<2v<@8~BCdymJ4pd28-J1n0scdt3!ipf~A*Oq?(-2p3>{QU-m^kzo7HTI_GE9J9xWhXuQhDD&%F zoNTKM87|{RY;mxD4ipg3Br80!IGAsMfu#%xB{VIt2uM@LmnA)vh^YQUUWxm@v?2;F zW|Xfy3T`e|)KY9=5UJYBi6u)46>B=LS?P5KkfxvCk+#HMgNjVzS1{Z)NCa_a3 z$vb~{*;vkxQmuTdTIqlQ&p7KNs&_W_hOA(5ae1lI?r|JH$VuMT(R^{dsz{bfajDiS zq0y~(U2j;P?C_*+5V^(#Rz0GSSrbGYJknpmoCyAO=YL2DET6mmH?AcVk}rQT1-_x8PH5?IOv*4M(E)OY8-X2_r*EFR~k0Ds? zKoo$a?;2!JjtXVQ&kFwcndy+oS`J>+9F-F7&9zT9?vMY#(0AM@$vw;{29#!}$=@|8{_<8XRSCAG)90}4W%%UiV#R)+E zk$Dxqu?sa8=Bmt=$RhdE-$bN3tS=^020k$iG?tP5DcIQYA;FO{2wq$oT*n@N11ebI zIXQ|&0m>@9R`txnWjbrC+~Ve0Ep{{8&8_x?CSO#PnQXS&YPguI>MPBUfH(g)ph)hd zaacEIw%FKMwqd6z1oFdRPNeyi62ZeDw7dX%ioPb+b};597;Dwvu-?Q93(Cwma26MW z%4`dDhBVf1RBf4|jCblz+=-CG#M5_=PlSf#8RGkX_5JQ7;KlL1yFuD4*v>`G{g{#q z^l9t_Q0HfYkYO}+X?DRE2xU}poxL%fkwc_JvQm5>1f97)IX*zVV(UhiY%uo0WkzwG z-=xF1?Rm9hU~3e-HCdUX|H^0k)PEEFnuVB!FWI)@3A+&ZrijiD;zQ~GoaZ3nKz@-c zabr3EpB5$d|2vBk0TTn`|Bxo>BurWk(j$tzyhGD0iqw5dLSYCUFz<=rFI_>fFR-I7 zHN+(c|MVd;ZAXLxikmK7X;JWjg7vfAU4omEjvs(==L{ZUvCErqw z?lh2~xJ_OfSWnZ}R~&G^!OpLD2G_b;a`q!j?PLR&PN&!QWYXHZ)jy+)(&xaau4?xq zCh2;8ti<*qQ){(S4mIno2#6I^>>3#83-^>ppD85Yh z#EV}5(P3TcXj9;hNTSsnL(rgoHjbn|CDBQE2*^q;(%7+%k7rMQ^?Zq+jC3;CcpYLt zVb{0W`$k_IAE{{j`Sqle%kzJ(Kga*w`u}IKVqpINTde4r=>NwJx$O4vRuXyP^EJKR z@@iz0*kqPSC6QT7Nm)>YE|v$-Wa>Br(ybB-eJpi^}{wjL0Rr$`dWwz;eq&lUMUzX-B{ z3M%X}xjjh$W}QHJFZx}6C(rSXlyIIfE2OSfH$6s2S4O*;80_%3pe^Wn+8(EC6QwpV z1wb2bKvS(i_*`GNqbi;amcqi{c37d{uNUQZ4~HDv4m#8Qk?5Hj)7{L4bv0-LOVIAg zonY@m2>Usi^s$NExhTKT$j0&eT-MMDRtQ9i@X$j0h}BzECju3?@jo=fZQL2U@gDF~ zTlzrKbVH9#x@sgjeh}M$CN~Y=2_3}gDQbZ+AAT)Pr`ZjD;~yD`W<-6-nJ5LCF=U6> zybRxyirWctvUBTpW_+hSlsO$cX^$*Y8hZu(6$-8t-~y>-nH@d@B{SX(OV&!MG* za|9t=zFxDU!)hKu&SD&)Zau=u1O4ptO!0<2t^~rYVVhR@?O|dX`Moh$_I+51^oErQ ztU;vFW)88sV4aFsZb?o+Y+_$=y&uKwC3(k0-jWSJgpiEtr&m>cFa}2vKat8Kvq8yQ zRQ%I|eDKZVkyGJzUiw{VhC5`o4CQNJkdPI?FA&}C?+kv@wNKiv{o)AyPwQ=opOuFE zeL9r)wuCOA7vue)TSS(81uqZ_AgObM7=57bC=L1WgWw-I+$U0e|Hz0Bb&XsRGLr>@5MaQ69&B3g`IvY7q z3zivpC~-oT|DDv+EKiGGW3`3XE)!%iZsKHv-4fq2mYa9Zd2R?}6E8x=0~u?WDO3a@ zFX#97`_k!*t_$I7cwHQS=xx~uZzdF16h8%iI0M`~&`Kk!>!P;cg8gXF`1i95-)2Mu zJ8W#FBabxlx&cvyR-lD!MUe{7hR0ZvITIs!x> zdoDz~%otxBbx>!pp)XtkbbN^f`2}-p0_PhUy;NH(AsG``M;P=`12~2Ld|qCbcbZ?K zbN9KMn$d?{BECLq&8i^>R@cD4aRh7VJOLjd0j;r3yZ=651kdPHOVKom=+%~Jo3-tV zP!hT1ZC{CA3V7pdL(B419HVwB}_Wu&Xvt<$j1=AGXCF`NrJ%&^*Juc+78GI z-qvWh&l1NgsE#IS7F@vZ8hIU7+KBhvS+@pVwelEby_P<(x&P5g93Lc-WDpj>GK2id zKmEa~Jn}GPP>1$Jn@AIAHgqLFu^KTO=nC62xr%4AQ(hi0YQm5E4UT7m?l1$#KH94C zo>n23)ynD~KPz_)%~0_7;m`#!OUxT*%fO>b!DK#f;tWY8Q~|9^27t`6^XracWf#(k zh0|R*G2k1(WL zjv5Q+0O1y6V?j}cm#`yXGxiol*a^4)4Nmni9AADkH<+uqx=zuOznd${tKUGo72lq= zRnSbDudfB1&R|=24g9u;!S63t?yZj`6yCuz5!+uK)jGeb!O^@CzqMNX-=iOh)FOI{ zWp6+^DO=n%grF{TK=ZtyPrkf{c!nmBmN^{4;Sif?l_#;mZf9uz1-=jWAeSCZ-J^N( zYp|TG@Q0x{20+t6q=J4+osDf~kYk}QRWwD=X8Gc6dDnbW!nj8jPu6X*xgoz*Lq6f? zLzeq62*WJ64v?0_j*u_()7Y^NtF-E}>CMTH<^{u>fEUyI(cO8PV_^iaAu{3CDR)ie zM>l|ZPfBUAABZV7z2xy<-5Gq|+~3r-MltaYccbO9$?eeJmN-YM%G<@iCew3{|)R3=z;l@!WX#~`r1%@>3G}oP5a|mce5Aa#ejX{G}nTG+!E|p z{R4Vbr*RhAD4zpq0G?zoPL@V(rO)^U{?IPhagI03WwmZB{#rZopy!VhM6D7+NRc{Q zZ^9F|@r}*yi|OJN@toZMa{9B)@Ga+m!G+JDo9xHZq~vnOJfR0pvkuc5C%V)NXHP8l z+9Q~JifsO}?=tXNZ27Hn5!$gJfdM(O{FbKMH}B~8)bXwMvUc4vIbQ%l6W7RqCQwIL z&wFt0wS|D@B(6QWQSsu$p?R(K@#TgA%Ry1PBQCI9UwKW+Bz>Bf?A{CCma{uE@5zU8 zSkX`Tb;Q3ed&G|k3~>^D%D)Z-v7$5PkghG&u3axT14DDMSa7OVi-3>r1#*$ym*zpw zURzTAj{A(RcJ}!l(+|p=>xO7YwCl;QgYMd-EtcMi z?~Y*v+c!!jcZBK0s}4HP<4<4l*Do33IfVW44uHs1C)DD&_)mD9(T;FY8@7%hjg_Dc ztarfcFNJAC16B4K=RKcVM7xI)d#@fuzSGXI`I%x_!fz=l#8`uOe8{B+saj$m41k^b zZmhS7_^H7Ta1n>QUcg!O3;ux*8|bhz`Vb~)Oe54_T8Z?LA237UD6yXt{MS$Fcjm*W zUusAW5Pv(C(}8;}uh3_!#iZvq`r~<{=;Zs4TGKK09UU_@MAX~PaogqP1O6;K4a(}n zEd30zujypKG=|cIB~EmG6_(S(D}(g1`$rv?T*57rNb>z!`e-e;>&YF}0-QK{ID`YY z(!Qwg%;}-vGWtN65*%<7$Q`^=hob(5>?bC*A1rjX1AeC5H90~8d3Y`kxqznVZVAL0 zIxrHb0F`^N$AF_j@omv9f~o%Sr73Fw&(KQ4==x$+%9TNGJ(FSgYsYK1yDp=6eS*|E z5nPgOvTbUK_(Rd~0w(|y;9-&Z*yF7J&Sao4kb4d3*2LAHeJ1PL>SWf=)z;beu)V#- zvz@s8usz$x)~Rhk-1GqZymjC)^q@^7lk}VTcXjxD_>8ccVdl`|5N|j! z@~CI|>gCgGpO_DL?mGH$Zbfxb(}_ce4Ctm8j`6V z=n}0ZquL<0p>$2EDhAi2RHU~}jGH6}MrwxmkK*vIVV+!n#C{p`8wxQ4uA%urC>5#{gEvIM6e?D6C#N!#Yyjn-ln$D4wq zn1Z8@e}VOV(V}oN4#y}hQj+#Y@eBpWv0|)LHyvC%^XbC9)QgU#Wk+#4wq#9&6z$lo zQY>iUS*LSu945Eyu2^Ikf3$bp6iI6WS7ybXFVX5czb66B99dk%c&7pU)Za~g;4R4Q zj2?5&9p^GYcgaXeYzF*&hRj9g3QPCgBS{awWyWq(orS>SPzn66-4qaSC+hv%rUf2df7v3_v%LT>^e8 z+gR*)?8L>f%RSJW$eV-*@wJ{=k?jE`QqcUCt3)XkUuoWMu>J5C2RBo&-T=lc0$qNu z{F9yJwb0(qzP|QtA!|(%o0-?nbvNC=d>I_vuIOuq}cqy||?$@!LpdyO*Z@ zEI{ph^wUEMKhKU``5hZUV>+c&7p> z+aP*E@$+-42(6$Z zIeDi9C<8J~{Xbuy43PxNy3liixgjytIPZVHE9SVbBbMJnmvwNTLjqYxF8AQ!qz)uG zBynuxTDRodL3Vpu2Sm09g#U{Adw3519nzclmwB`AKzE7Xck#xKaX3Wy39)0NN62e3 zisF6T?F=i=bYN+2wX$kBPGmiek!5{2SiSTZ&wiN^C7mZk9L zMfJ=vBa5Kt1-2atp5{arat-CF&Uq3`Vu=>eGQ~FLSTdzj0LFQ0&9m77o`LQGB7^Wc zX?4;qI&KnfqAGN}(d-9}eGh}m+k!foHQGzW^I)F=-+h_=zqdde=b-}z`%L>V`&Ro! z_M+@mpVXg;---W8uTBAWk8bY}-TXgA=m63Uk~7e5{l4wsy`mh0*#;SFCa)Nt*_OKM zOR#66Ys$^ETpKf%wtpfj*Sc(L^lPRkYqsk}uXWyMXs=|Jy01%?XHKuc?(rQ%yGFM) zpl4dI*zQ?g{U3dZb;4)Dk1(GpUW3qeq~|}^in;Z(>kO`0KK(t$diA2uEFU30ld^S* zmt3w9*`{V|FP9L{#9WiUhJ1}qm${ed&s1EqzQnr;$d_)<5S@MB#^~#$Yw#@29OM4D zb;!D-iwZPduy%dGYqPmpP{RZK`N9|kTO_bZA<)GG1P1h@w$RnJRr;L$hMC9l1_j02zKdt-!@~Ua>jdo_f2bH*g|s&lh^yjQV?d{cLcUnwqTE zuhYk^QDqoVg`%;TT(+M<;fc20SI=BzYO?K4=S=`6)0qsO)0)oHnM^&G*#IweTFowF zK*KSWYE8$@_c8+a>)c>$l}4xSS7EG;`)7FcvK;TzBh#$y#^=_9Rtq#;*Xsi7&vV8` zs@vt3idwJN?2b=u*GAn>^XjhqLv`ye$L+P(KjBquVCddpEbsTxZM^GAuUIh4Yf3<*ZD+au~;e5$ln&S~NwNOdiH|6qb zkvwqMOU!U&Y?6`k({}3I#{{>xQ?UA^r=cW(WmHE+32Iqc)9QC47ydodMu(Tj_BVp3 z=eCRS+FwQK+H(Mn)5mNDz}M2VIfK=3<4^$HjqW2T$Cj_${^kB9hrz(3HX>(j%eA{E zv~^TnM^tOAX3m4-Y4cSyYJNk(=id22ys%6;Cv-JJ_jEgH$#xy?{cmDlcel;peX@%whDy9G z#vv}#{fS~PeM8iXfyAh<*Spb4R^5+FWVDu75^Z}Iv#R>eB=7vRT`Ha4!802yMR(WI zV6BPC8u-1U-c7`Dcl|{&#ZZBO?PWAACDl`+$XapcY|tzvb8r2QE_bP6!e;H0>x-;9 zZ#i)4Nc$E7h?$pVmTWQa8sv=b^>Lt7H=dtBRjak}Y}=JWo%i0QX6S*dwnoCdYv=m! z-bxCHs)K5n z0<=FE+VSDOHn9=MC$!wT4<91A z+nol=)^HT*025!$ekm+X$pX6rQWYA~>PuAJrK8kkA-yKO#I1L_0qe+1mi)-vwQr%j zHF=MD0=xOY2F2I9lT-r@G+5rlI%Qo>RvPTbv6l*zLksp1BhZ$AD37PBliy^@`)9ph zqCYZ8@z<>mxk03F^07QE*>>!uslQQdKS#>>Zr1WZ(j9{@mP=S8B$3XCZ3aWoX zQG9`VPX!s#k4w*-vgP!KX>~uaHY62Dpo%-mB`>i4i`ug2rn{4y>hQWUZ?|RRxf1Q~Z+=~k7|FTvbDq9jyt*fl*0jbg<7UaXBp&J%u zM>m!31*tc0JYp%8njxwxMy<+qB#8C|_s#Rx4Tbo93 zvbzxiAutQ-R8dzV97HaWo#Vpym@u^~SxjqbnfFT6qw~}+;H?b{Jyn9ZEb9m_Yf}*+ zSgAWz!a~i9x`Tr<%+&_*_6eIe0=rNzYqg?FK**a#m0X4LRnJ0-eWTv75xZKKo5!;o z^XWCjgQ-D9@@GbuyuV334LC|t4jE}ii#1}T8gazxaY&*XQw_!$s}lcA`AZs*Rf$>; zF%OazTFD1ISrYwW>D0A{bWIBKK$wWpuW3}ZIv{RbRVQAyeAW#7)2W|Jj~ao50>M|! zI+DZV5gS(`TWnL!lftCDVh%^qkv6AEP#9g?&r2vPE>DV7E7_-aHsA$}6aWK>$Bp0s zn2QA%^z=Lu>^Qyaruib4{6Nm@gYYOvc2l@K63b%49G*#7TZ4W9vl>P$@I1PV35LvC z;NpXQMXd+{Efl)*fm`q_z>B-By6-qF&v$5&us@GlMzQj0ynD)cnzHZT2O~4o?*}cX z=$sYS&VM0>%6LaGLjim@euazciCBtl@R#m042!tU#mu1sCJo-fwiqKC$%SP(m?#+|Q<>E^5VhAQY*NVphY+Bc3!)Q0e^W9Q5OO&RW~&GKTo zB*jPEsudxHSpmtsDv6WW|FpHMR~4m|0L$T=%GV@Vlf<~=$%(NIk~W`fShpIl#LhYC z8xW-6P;e==Jr?vWlxB#00@Xzm7V1^KwJ4{9hXVQFRZA8X|5ZsAFn5;LlpG}`FlQtb zVu}_91O|MC;5G;h-BW^V!L8_jy^geywAhsJi$XX~^4Nc%6eD$1Ci)K*ILVebi%408 zz#Nou|3Nth`lyWmKge^ux>Lm!3LaAk#QZ+`56Oj~9FlSWLHU0tLIUt$94JTf%Kz^s zPDtUuz5g~1al|nHLF#x+Foyc*KP3O}#GW`5n`3KiU-dtT!m~NHsr-ld!D`2}_`xU~ z(jz>oeza;tz!?Z1m(h{5wY zzQzyM{)bo`-=o{g|3Dn7cU&eKV|nx+k_)joD&qfxN{pq7Ln$%)=#TcFpHV5H8^U6& zEo}=_i^7Gs+d|3HeudZtZynBTV!k#%z~6Dtdg5WYNQUCOB4!j z2GlGSz9>2{TeZ5UhfijpwnXkU@=9RL5FgV5e49wS9L!?%SuQ_WqVOg0YKvnn%#MCo zf0h<5pp5RYDTiM-{|gLPgODF^^(Hu0v!) zz{0dd*zx|igxZ$6SSxfYzXxTmMT!WxA=z$#tv~BCmkSim%j2ypd=?=!cjP1~@2|=w z#swAC5*4G2)nq0p)bdj3n9kTll(1nhIu~zX&W|!L>Y^5Mp+Cp_3f3eiCNdPQ=#=BgxT#p79Sc_0(37&%669joY zth9CFNmknK-EH8CZiC5x8Xe9RLfZ-pIx?;!l_WMPX6Whz|!KyS#HDUvvcw3 zFBsgqsxBPtHyj1!>bFeM>h;kD*e8b@M=cbU+jBlr|8c%q%lY=$$+^C|()-CgSoLu5 zvYWlS^{nkL-qceYd9JdkZMr$eU2m*vA?R(ojp#{fepbo&VT(R~7?JeQ0}J+3(jJS1 zan}p(sukQ(^HVt<2_GPRxP7P0DIo?$$;s_9-lSQP z@`sO7y3%FDOl~KX>(v`H=kRPQL;9&p+H8gF{q@a6)5dfZarog+DT}Ne>$7}jWL4I? zpmM#jzG1VS%gFhbrJjqZOHEKa7n?ze74oj66(buIJ&liLBmq4~HEeM7;K3J<1~PiB ztM)W90AK=83a6~~LuIu<@~qS^4bjT3VCAbe5fFS+B2?y3PUGzkw(v|7p~?L(BA{n*4@h;8>=k3f#TR^40io+FB}s0}Ptgv-XyeBz;&~KV{s1{_ zu$hC6-81l^uOd|Cj$7X&JCnj#kqAvbs^5#+!)$}c3n~rh91GY(qwdAu34mb_pmV^U z3jS9AA;W+%3rdtn^G0E=1ATPY#}>Dy{~fdU!G<#^bW7hQcnz=Hr(38G)RKx2ERV5; zZyms_KCT)m*37jBv?f%vceW=C>-XD$Lk0m4$`@>09$an^hP}jjq3``Kgl(`$T?~6r zEBzBBHwchn-mxIUoyui79jrf>J{ff=%`I(x!tc8>cUpI~Ta*fQlA?n&vH{G6_{YLo zMxi>bTPFF>${#4uK+o4Jz$WSQXa`7 zzGo)r>)WE?bGV# z6#sz3@C*D3zY{a*OeUz`mS`kDQY}rS#k7*H!K3kuLVw`_VL$80y0cr^2kdikvA9AW zDF>Q11s)2#82B)_EBGPmjtSdOhTbUAdr&K$g;(KYZ2dF%0>0t;gY9=E!^kbz%T%(I zJWO6BZ;}tm_c%*X--)yix^O2JfOo|A8ZJg!8xxPU0acIPN^sn-r0LWGK0rj3o=m z67nEfM;;?jk(Y1=I0q`@*wbkt9Yjacv2-C_LRZn3@x7ZKphxIYdKO0>BY1^$p}o*o z{T$~GoWnHrn-mY=dy8;T_*gh4oEFaFs>QGbHl593>)B@ZGW$@xQM?`BPl>OJ4dRDl zlh`Ct$tlH2nbIWbIq4f&k~_&I@-q1o`BzOPi6dz^a`)vQ6jKMR(Ma?%D^cGU0rz_4XlL`$9v$dGZj%ne%lx}ja<0^k&4F|9C!7&? zqegW{PkJgakv+k_4dw_>8PTJG}ls&-35C0%M>7z9)9# zBiU#VXT=%fYH^GBviOSlfz%$Qy$~Kljs6C;S%)(i4Ijey@CVW0+Bl#su%$KVwHk0t$KgAac2FHxTl5P($q;Po4;Tt# zu!l}i!v6{>xD!29f9NT^kMd3;X6Q~5$ur1Tffj0lc*qmKB^25Q`UgAHiNZeIV}h7p zjk{MYTt}whC?aqk%@9qBp<`emjv@5A?Z1il{}m)3u^jPE2>e?5g=+p80Y>%^o;;9IRFkFfYXZj zCWN@&013$F!dSr71mLm#4VH)T%a!nAze%41Bx9Wvw1zg=ZWR z0f$Bs160^cl0i%S#18g!^Y8i1`Tfo3^ZPaDLjk7EO?YXa<*|4yKD-cM(Bu{xniT#A zS8mq8zr%5}u$|l|?#AxADYnJpA0m~+apDY708t=BJWoNWBN|1|KVzcgYpGukdph<} z-me)7`kl=q7HeK!`z&(jlt`hYCt7%*Bgt-uOi_3pB|_u&l3I#M8OWNMlb2) zI+CEoN*hRLy-s&0NtTl$zy)r|!qGVl<7b4MKhb=acW}O$Sn|Na`-t>JM@f>L(y3Ff zcO`M8O&^wfQy;pNI1bENRq37$^UAE%MA_@*V7bR&H+(MSXgr1^V z?Mna$d-gWo*NO6e=I_cO^K3bGfs!husbmRp1WxhR9>U8DIC=q+lxW%+bTs+0(X!Uj zs={cW)dBe*;vXGyZVE$!r

024Aiq!i84E!Ax%TjVX;&8A)2ceI)zmNHwJbBJra zWrA&jbG%EFNAsjk+D^v4w6D}l+uOKV`yM?Yy`g=>_!&JWeWLxuXffN}c53IJW&5nQ z9Q!7X(G`&yK_e8ri`WEW{Lx}Ym@_fzsNUiE_%(HW{m%9`|30N33iNFH6b@Xlawsn+ z*)cYYS(dzsU@_-*ib<4Y$zrzII%Ids?PM`0C)4c1v+iF#^YD?tMZ9(>vBl>UcL))& zVcpAt5rK-GYe-+Ri9E4$&6&c%w+HaGUnv}X8;YIoFGLAGg~Crp8E9dMqP>;gMOW}Y zUaKQ*YDb7ftfRN=(r85j1}*F%r6@B(%N3&t%*EWy&lq#)c9YGd8bX53@5glu$JitGEo@VqMsm6#RmyetVLj|U96g+xBzux0$tl>9 z*$}qWz9Du)+=loqaa-awR){ypyW`u(&xl_bzdHU%ye6Kni!CZTC!U%O5%FBrDAyGQ z6^MTg0oMrX=##aS7$W#L%DgT^rhyvx+8H)QirS+#8!5&iJ6#b+%`>SZp=ANjt1FnF z-_MMT*qlD)1e$kx`ILOLK4R&RUe3Rt0P(?w8cQA@LrsKA6q7lRY0P<|#)8z67y3#; z8DIUP0j2vOHrNPpi1=V*=gytW$dq!_35%zbH5b>vV@|Rc6~fmksYA96El-x1Br`)( zin;p7SJJzTEi0X%37mEi&0C*cxV~S9!0*@Fh#0u^Fwq{{UNH2gTgFbhEAI5W-@i1v zc2wc{l4QOT{m>p_aV6Tohf3xu+p3rY(ZXGEE8^%T;dya$)J|cyxHIZ=`xg$4EsA(_ zMqnf+(&lj)%?4c^Nm8_m@qQyU8i}orP$j|@nHfnVx$q)4#fk(4y2FfGgW82t&&F)F zDaGhFG@yhHHuKT>uKQgZUE5r*x>ML zcG1S+3vXMxe`@UBMf(Hi_&4>3qdYr`n^3dON*j&IZOFCuvi5bXH$GunYyI4$wOS&r z9*fty$chFqCXth}CXtiQ98KX=lqg5Bh{klSg60#ai_6ia1QY9E`G}O^yiqWOZ z)KMK5wr*1t7qC9cmgA1fic+G4s5-J$iLzK+=1eoqG#8kQ&4QU%HS@kABO**J!i*w6 z6ho9466184>WD|N8fTKdhkz)s5w>xMobYiyxjt;@d;w12LZ}ID@McxtF(bWoJ<6w` z{FjLB(oJ*CZ;;kSQCH-OLp8V_0UU!KmW`OocnCYeXo6v-f1XGJPkEC2E0(Obe*K1 zu34g4>)0%A);w?85?OEBY1tRqU^y6Rj21gtdYb3hcF>Q^hoa;?a1hxUk?mGt?ae8l4B z;2vdnnI~@WUkY3}_+{W5lJ?W)W6e*_8_<73<=_F8Y*51BlIrHW1Lr^aI&hAZk!9o| zGGL-nw@9$2tZX&+(9(dnJ~F08Yzk2plXMgNNa1N~=u zokvgff($Nwrk-Z%3-rZ$LC+_w-_193^1?1k36nJjO&uw%&6Ej7L=}pO77Ijh8ZjI) zgoTjL{baxM<<06QVLq#>4QZKsI_~h%5~VR7t2KA1uz%+7_mIFp<+E?GCyDs}^uP^) z$k#{~o%JW`6t)(Zb1h0NuH8CJrE7WGC%D>?c3cVt?TXvccDw0)=&u`;NSi&UGOj9) zR>zUJILT^GC8=DWv{*AMRY|3(b@V>PY&E(PNkL+9B2DCNB=StBB)X1jXQm%5jvx`v zY{yYyrthfD(f(iEpBgQcPbp|FPoHAuu5U{E+47Jom2;^2q)K&4IZP=}PbbOA9dkN` zHw*6Vm^U$nXGLD7R>Eaz(&zTkCqMr1)TD|z^8?MFzO(4@8TBKIODab6A5h_(SvK^} zX=UTb3Nh`Tta#?gk!QwjOl!aQuJ-~H?>;*7Z8Bi+Eh7dOkEm$AZrXymGse%okH=eu zxMERZ>wI4+?P@8qjMdN4EYmzMKCjti+7!71>V+MqI?KzEZ^FBlhDb|JLe9TZ9|-X1VCQXvZ8hRc^4}#AKq%Fi)LT{Nnu>W|p*U4m1!l07srn`v#$XCP?*c_N1xFfJ( zmk_sf&0Q<+TU3P-Jb>HuH!N8_d9+hvh0a8hIy0Sin?R|QOx$9YNX2cM54Q5tMmaxX zqkbWX{mNMO#+5Bv~G-B9r{~Fw}k!<+@x^BvN!kdHMZw>=yp&j z1^NBX;`(J`l$M^)x2Pp^-&oSl&WUW!&tLM!8@RMZe*K^#f5L!a7`q9)bgUl7)gck4L~a@k9!O_-f#ls^*=u18>o;BromVw@AN0t+=~sIdwNT;>xW- zNsmHFM`HBZ7LF-qiI(3wrCn19pz2*StB*> zC?5eDn^GxNNmMFIP1%ONhzG7(eGY~JEAd3tPH9)tuA*IKyQ+4p+f}#IxZ7o+XNpR6 zgF7+{!?8NLqBf)bpq6mG8AI0cDZi(O0xI=X%AxubHE4|vR@KDkMf0H5$w}4rNFJw_ zVWrEgAS9{?{vBeS8^yu{E>Cs>ZE-btE|f$MhQisoow#>NN%jgBPxvO;yN2HI($*!z zCXZOWy8Ou*Hv~=wj3o877t?MWT69C(54R9&b$a(f%ItT=-SIcCA2I%g^pw5x$LyP8 z)KKsChNtu+5^IydYKF~ z^WTm>hql5cZn5X6RA)p=hAA=j45l$DCTotVXha0z?pukr=io6SRY|mF=!A%$O+(;k zz$PhiX5q#Vol-562-ziP$pY?{D{Eut4QdUp`kT?)ghPe%=;lwPbIKF^Ohx!XK$Mu* z%^i)$9b=0Lg$#H)L|4NKh^u?xgC7IO153#ql0%HojmZuib3Qxc>G$5Lp0S0-4nKE> z+)sv)JIEs&Z}IoObK&=ai-GTdT*E!V!>FGlQ9sRike;t}NJZnmK4vT%YY@|7@?!ef z%4`#CVqQ$A*d?*+#Wi}-W#LL0Y4t^zHI9^ReCrQsB%hQLS>+*aPZqjmixqXyoMonF zu7mEs)xlN;w<%chob@ACuHC z?#}HqB0vAOLEUzUyW^5y3!M7Lj(e*|7p1w_YfT+Z)*)|h*|Kw-)xW0O1#3T1QGp@`lKS-6UHN~py>>4Y<3GB#N8JH zd;SPa`2$D47DvAjN3VrDl>!{SB>H5xCQI|G<|_@$)U4J}jRrzf(Bk+Dq+;|L0|ovA zHBPraOHcJzj$ik8<1Y^#=9}}aeDHrazO};H=B{*1^9DY)XD>8Az$H5hZEqjio*VsJ z@6HKD2}9%=ni+;gnuUf%F$-h0Qj8R9jj_h2T2k$)&eQ}=AN_DPSUXHViQUEK*rz#n zns%DsHoj&4)O^Zp65=E`H#WuP%yaR$ixOgs%aF8IZg1A2;z$z7jV+QJTbeB+LIB() z93wD0#X5w#+-?D{pCs&;O+Kn4mZtP^+Z2TQfZ_3(xtwCa7{sV!N6`e7|08X zUN0nTlJx?^LjxLxqK)g4qjPuZnxm}?Hr9rz@=RPi%*BhO)#$#}{;0!UQ>Tlham=iB z>AbWpb89noIlg?t#Xt(HgXm{&=*Iv}wHnP>)jk>qA2Xvp(qwI+GGuT&f>SC$aI`3A!0{Hj{hOBGyw|q#LRksx8&Yc3q|^ zhjw8(+OE0+lPpjJleAi0G`BlIk^rU|^IQ zbQl=P8kdRSk=t0yf3asb?X0f#@bb_a#|#>rBWBBrJYPdJ`{tu)_UYYv1FfT-6)P^T zf)zo*N|5d1(Ev7MY(E|2zw=Yhrl*_pe=_Gg9p>gK%~SH7c08r0V}|*}6n=NQd+(d?^Xx53UKi*@8>+IB=cU;jZH4-imBeOj<$GID{Atv!aILQbVm(Um( zEo{^Hg;zEDP=MW`V-8h1r~!7PV$96Wp>BSWqdH>FT1D$=mqQ2RMXlXC!Hsu#(NI~o zQz1rfOH<^ow1eEAD)P;Ah^&pGv2s7!OMX<|D!)fRqo?U9`A@1(p{eo>@+^6&`~sD@ zz2EuQ-<7p2aT%y9%@DnV>d9k;GW7GO(9cIeEIg&$ zv{qcJS!Y;hVj3cwG!e2r#Xd_r(<;xj%!*#jmT8t57Mm7Xmqjg&UK+F1zSwDyt+>L@ zXsa{IX^(cwkr_s1X=s1M8|?Z4Z;{o5~g?P{c-G_I?xN$-LOvPT1t2PR|iG~v%cFc@sQaEZ%-M-mrM zySW@@Dn3c9kE*u|*NbGlctoUDi_d5>L9ChY#Sx&f{Y#W&bH!(c=O@OSBQE!-aaRUP zt#ML#Q~oPf!Ue-XFdS@qy$*^~3&+}zkYmI&aNd?tYx_?+u>YxTGkV<8r(?Ca+vfRV z+mgD8mgweB*=vD{cB2YQCKz?tF+Zd1#rZ^o2QDZJ@*?_143#J8CmHx>Bh}uWrlVS& zq>*$n8k??@skfQ>TdQBc_{Xn?Kg+XK80SX2dVmE_E!9m$bGh zts%lR$TZ!w(DbnBX_IJj8x2uLqanf&ZH%$`BF#~xBC0xyMn!?!!^MSyiw2E}9|u#w zXf{&gC$TBjl3!|&4oOT}Qt2gbZLil{6`n*_6a z@jFxBYRm8t5{-wDXnXotact@|X_j$X>Su-{UPGDgCeuxcW!?#fan|vkiK*k;&Wv9i zzs6&*dim~{;L71t8S8N73`iW{-JiJM%cdkw@!peokN4}uuf0;bF3p&fnB>hf=6H*A zMaG_qJ-m~QW4*JDa}t*smnUx0Z8koa7^&51jZ&iIb?6*MTcVuk)fpLy8Ddu)?wrYX zGTFY-PVKwtScpY0WWazdmc(X63DAddx763^&fyQNOGpJ-O{$5XG!PB>i7C!JGb1b` zO>6%-7(-%|$e5g%A~_}5+0Ko_b{5#V0 zJNcPtO8WWo^b;X^XZi`;#6qr14X+bX9JqiXW~CNePs|{4SXLsLcWN5VCn1u zIelZT?Ya(`{Zi%Y<9>P9IAwIl#Jn6|=D6GUt(bTGR>FUjmH)L2t5=`c+^KjowOK4n zEYVhKtF)`NvP4AcV*-^yqm7AiviW?UBpHfMlHDW=_%AB)TZ>>Sp_R0XuBMDSG|exB zr9Pl^J4LCh@qcqZUV4q~c_Qp{^3_ldH-?Tp`X^rn`mt4k{_M327cTMNb9xAOgd`l5 z1C}eDWsR(r&FCbw*K4lV%0sn7%xlbRE$gBmvu!r-vV9tTQu+HB&0V50vA4CQ#SIko96wFQs=+GEDpx`N$_(m2t>oraMnCETpjG}lGC6$LXObS z*k_{1gT`6nTC#?&XY0g`8jS#YDO1A((+bT@B0In)wSi=*FI+DT#Z?q2brXof#g&BC zr(;4L9i`|c!1Eo(KZJ_A=}7*=R$O)UjLc_M>aSxmR!8)TZoW_@d?hqu0FAb|18ZQk zxSQyK^5f?ppz`zO<>~gbt-;{gD?`E1hiB!GPB1j^5FYXos&76|3dvM5 zo^)ycRos2)b#|S4N_a3Znl4oJu|&z1vhY|!#as{ySTUn4mzcpS@Lxn_q8T^8^WtLw z{6XF!B9IEr_`5?7EX`-nmh+L|KPV_@#tek|>@wPG=@9)O`Q_B9z-W2s7Z*o=!EGQJ z`?RZl_Egde#A3C}ET*VETEQ$!5_O>v&J&S624A5BDzs0}Xni<}jfZ-|UitS6FyQIf z!Q$;m?E%v%^xzks|3ch&42`94@HA`3x`7w6Nq=R6?9{}G@iylTv3=tD`i_~uvS>Rw zdOLQI;blhJBlR4x?rj&DUn$n4XC}E2hqHHl9?oK5M zt&_XdTs%dGK8fHVjrtf}{p6dB4W@r|aBp3a5bFzkuQ$s=pJ&RS**D~|2j9H0WOC79 za!aT0lX6RY-q@>ySx>)d_vpiA%XS6oRxY|RF4v*y-MeP#uvJBIK6l)JUR?tpS+nga z`CW%(C+8-O<+0onT&8dA(L=FyZkSocuQqL^+B}I#REX09}knJP%cL@0nKh&>>rgc=Xtk9IRSC3shydsPTz5PgM|^31>kOy-9?}?fXAYfn)W{We z#W+!#sGDdFX^T`|=J9k4PY_Q$F?g!GTvgb}z@@_N!*&HO1zxLJKpf51%${>bE?qc& z%#sbm%SZ}Fa3Kgv(M~$a-;fb-f5PCx)KF(a8nIc+R*}+Ua~-_m1I+?x^8{{D;vP7ZDe&#Kz}DD<(@$ zMD(lC2cv~(RT~ltRBDPrN>?d(Y_OJ?DooU5xAI7Hrz19pbg-(=;N#t)XYq+`LNq-i zMD1}ZRU*(?R`cIOGUKpESgrhrNSNMg=i*M%%itlI(IF+uOc;?cIbmZ0ONj7j6k|jV z3OwxV(yw?Zf0q9cN|aqmjViD!2@!Zf2W#h^Sd9}4n$JpG*KrU$YCIGfidbXlMPl!CW?SHgMH5NX$7hLEYF2~= zBfAev5oQg!IX|C}ftim!x#NK^P#4kzZwL0xUD1c!HfMg19#gsBu=D=~0M9Zus8g~# zF_OmIX1Aq`RoO)id(}>(Z5A43wOLG&5nwh&@}H@S(rO~~WQ0Dbr+U5+I*C{!Y$RwS zHh!DHf6eL~|8c9xD4n)Lfu>kfq7gKy=1j{73$@e{rWj3;$uw#NRNESC)W&r}Ysj%V zVrJFTiJ`Blq@zpa-?3~e#~{{m0_khgyNtf|R8x?R`tqmKfoHn8N9#R~@|y=|lB&8A zJ?DPw-n#Ye`qRMe4^{pD*wyq$vncnyRKhU@J*y8zHRr z(^#4u`00@?&eAlto!TZx(vw^?RzKR9Y?a7N<`;eb(&XML(PIfjN&TJRw}Y>)gEuhy zkiss!)H1*BmUP#m3fn!W{`u}cOJy^be^2hs&fB4O%d$*1~ym#EVw?ESDT~Os~ zuesyfKlsu9)7Xkb|MkG7l|Om$%S%o^Z0GKM`ibv;=dTVwL3~$;r3S%v`_R!?qXRF* zJw#Z}8}JRTU*k`(B8xt;mb=Y0?h-NPDm*TC1@GaogRpKsFDt6*@v1(AtZLYz#Pr(e zvkJbfU?oIPg8Hg!qhAjk4ser!3jyx^01hBe*yp9D3CbS!;tO8v4f^{`_Cg%XwqO9d z$eyT;CqDXl;HjVbP?ja^xDasy7I0or*C?IRBm&}R_Wm^f`1<+9bNbEK^`|?E;LlF~ z_Ry-yz5A!X!L>hmd*||fUz`3N5DofE&(YGI1{qDAL<-qkaH)MUWrM=)QI065l-HH_ z6>*`mRoSf^h6It9WF!i_gPac|I|@7+0>4KRC0S588RkW*aaFZZA!uQA&Ctt!t6fb>xqY(b|O~hUPUh!u9*Azo9dN8)uCx>O-zgT|WBJS~H zUJ#MjV{>Xwi6@KwwhkwZub|K8f05gUs<#jFVv*!f31xDEtz!<}1Z%I$Lw(jrS1HE)GaT%Ew9pXmZuitU8oS&kF<<}m z)7PH7!{N9fh>N0MbbR|4?cd$7s^G?1(iYTMfv+7Ig z&z0BIH&t~Lzm?}~azN>qZnf-?#OIZ_h4aEC;X_GWC$F=NN_PtnkslTiACn%FAG4?n z1-H~FG>Q#UgWOh$=YLimF&tQB`-0yqkxZbtv7*XLLODMT==?rvkRoM+G-I3Y!Tf`#MjvVG z|K67h->U-)H9vCmwc{_2U#qE}Hi*Q1~AT8%|%W}uNPEn!;+9lg%0*>?Z<#p8^mRg z##X(9&sjdI_{b}~!o4GM?w}Y{xIyPF6}R{X1CMeCrGu77wG+x|?q9^Wl+)Td@tpLI z&H1F|HSWJlKePOuCKfFFr28zqi)x|OPgvv;WKWMA+B$D?9yiZkh2{iOW;kkw7o|B| zNjgU%x=02DOeSzVR1tNX2YAUD>hPjjv-QRYrXT-3juv12-JcgfdI0N>q|*luq|=XZ z)em9mf#NIg|GxOM`z}BAou{5U{P9Fk zx13*XTV1hy-Y4@E5{;K4tc&s|^DHoaW=GyWtJUeSmm+Uhz1{8zJDoJ7vR)Z`uRXs6 z1nE3`RrF0~SmL#i=zCT~MNT+*iKer&ei0H>%~1UymO6g;<&&5zUOIW({`DYY-@~KB zU;SEQY%hp*!$|Sh#p&Y3;v4;&r{CpI9((4AV^4nX5GdsR2=QH%_NQWXkBV5a<4xkI zSP=PE_igrZ`=nb?6^FJ^1^_|3(sI&l4R_BXk7Nia{a00Zu=Ngk0+tHdM z{!Qc?Ey-E0Yq|&N8y+SnOxIa*;lo6umu*|Vb@0}e*Im1@RR}-2ZF%R1Ela;&{5{av z2Kwv-8XLHD>^qW6s%TJ^oPN>_M=)Nj4fw%*ZSbwjmWT^k8^X`NM_ z)txn+wX&p&E~P49i)hu=)irW$b*w3;?ey&O?x-&`?DgK)@R;{N!}03lHMTu?zyG1Y zw;G;qIMO6lpSb)Q@u#cUy_#;d)RN~j#}?L_&%qFVj?DvLn+-3n?yo**`)2ja)&Ep2 zRaI*?K?ot{v7-*+yC3s6_hA;?(dX(#QM!9FA7%@L&HWQ$E8c@IU>;#7-Axf_$qFBo z#5gvI1iVGKAaFu|oz)kErhOg$7_{q;L8JayXIIou))f7*MfGrjb{+nObooy3Zw|%4 z-Z?^eL+Emd3-wpX{wiOrswV1-RW6J!^x?N52J5g?ZCJE_5w|E7m>*pfYNAIGU~<{e zgxi{MYZGo-P}K&GRR^v@YyvXR#i@Pf^sCrl`fc2Kf@szym{jOOAv2WpxFMNt$X3n} z-OFKt19>Fp-LmE*2_sm1+{g~w!oMN&eVW?Kuf`OsyU$Sv7m&d3p11XA9<7IfM>VpW z^WJmT9>l)wbFh3)m%KX@2}f!p>^$_GZ5#3~2=V3GaLAobq`DS)ysL{p_%HXo`P(=D zsjm2uYs+n!HoY>8|J&egAH4s@G;VF&xVf&fRrh*aYp%cLTMzu?;RoBVzhR-TW`VbI z^u{$``}2Q1g2<1Kyu*D%d;;wE|A^J=2m(U2-qCBn(LU&qgI*NieO}~uS9q}B&3SNu zS7cSz0z}Xbpx!+gxHS(R3`6+!H|g}x*r#OeZk z*zex#?eiS+JnP}NdiHp}?s?sF!6PD%(?ebh5j?@r&cmgNf6b9D7}M9%qpqIIr^wdN zC3EM;`2mfa&(rr6q3Bua0<*Yz2t$zUp*;0VY)i#e)7jCv$i>}x${MMR+!z@C%1w9n zSd~Bd6C4u4XNm(~ZLFO4W<$r#E7}j>e>n5Yzbx(p{`?tOgiS&i=JLm5{##vRu17>( zk%H0^Zi#CRx5jmjlWDBw60AO?dOaRhkt#f4uNM(xX7|w<-CR8Qf*D=0l&5kFzF@(Y z&kwoG>EMc)e8^lx3x~-jl4oW=iC@?I)8w}A--Lq;H}uDX zc75S2J_SJx&}jvq<#wRcivCy3E7pZtqcXWjU%(0zKD}gCiK@bJSstVdX6cT)*M+vH4O{+n5 zLPTs<>ePtVj=IF_m4396TPd!RS1VI!r!Xb%RCcOU+Wly+aKE@$*{j~Ky@B2kPK&3N zH`LSGd+0sktaw&=Pd%%Bf<6&0iXY1tl~2@*TC;fK@-Jh`yxyn~hKq9I@|*NYB~Mx@ z50NK{E`9f!r=4s7SYvSc8>=AdCoZo&CaDVCZ;D;RBTctTJg*@R3mPw~R#~w~7Fia} z9YKj6Awz1bz0c0sL86wW3MMbKN?ZzA;S)nVwjbAV(Dw3495N^RP;l*ZC@?)83Qh-1 z36^&No$QYuj3Dbb^om^m9%_Qo%vUFaBiM+DB|dJA*?NGUkB{2OM(D?2hOIG;q+9?q z%$qlf?7myc)0vV{rYn`iry$BvLH^?^p2vg5BiQxI3)u18YuH$|vz#__Tb%CR*f>5RmGmF4S#Vg$MCha6wkX zxKUn=d*yz7qkPc%vGlR5EE2+UgBlfj)n&pu^=E?RCUrm;sO zVI+DG5+zXtKhL7TAQvG}KPq)7Bwn{#jP_U&0rE*+T44-@HWcz5v|_|~8N z9lo)65brBK`Kvd%8jdf%g=>q-^e^!0;tRwM+KV>}8$o&%IC|V&C*lf1VnB05Ek2tg zDwB&uE}{?8IP>UlZxjM@!Dh8fP7YN_LIo#)wvYwlt>A~8z|Y3qR)?+CUWasVn|G_1 zCyQ#-y9!6?TARCaLDWl5L-g>mKrl*WnA zxNq5_Ww-9$aPzw04V}Yx1YzLVxj$UuP7V!USM7SsmK!A8uZ9@opMm>MTzB04s(`_> zyc}zHx}qwEi;OKQ_YwYB<+`jZ)s@<9_%<$yliY5%mI=W}m(XDH3+WQc?3J|qkdo1u*=4p(7KT$JZGBF$GZo@&75PW~J zZsyx3#25em&WE<^1)u~6%OFB%i*P3*-{3*NsF_{~3=uTGp1~Zlh`(kqk8TrBF<3wz z@gEs1qJa1ggC!J@0t}YX%TgPIEhsGSVX%T8usy|KRrnj)Gl8vW*nSOzH8g7fCWCF# zap?mF+tHWo|A+o$B>A`7aSMYn5*;5hm_vel1%r9iJ{jKaau^q)Yzm7%U*Szn#J|k&AylgFzPlWfZnRy5>(XSU>^) ztrS+6d`;MtuL+y-HDOb}CTz;rgiZOHuqj^?Hsx!=rhHA^ zny@Kf0;`l)cQKgoDnnr_q`UnG7%ZR#{(ThIC{Kb!|K2ko=!(b>MXr^$G zmfyr+Qhp_c=MfzUGA*1mRif0 z>1Y$=OwiwnH_PN8Z8hA@{@PIw{I#KG23e+9IJ~9I#K( z7L$;Zr=`bfUxe#<)~!)&aQwEaBfr|I()ZF`*cZm_Z$+LqaODSd*roo5_Lz>~?DE6e4fO@neJ33s#Y z1WPGUP7_(pXi0|3B}+LvLF*GtiFTw|tx^vOT7L)YHOVL?c_ue!xG)MONo!{63}2Is zyBS7Fl9n&frx~f{sK!oE>^@s3N+Ty%riJ9CXnQklWTBsJ4BI&4e}d|?&h);-vk}_& z7)>?nPeD$S$&i$p0NI;5l7Z_OlSw8;u_3x?$}Pu6@sdDTQ&fMpmF4{ZYWGdqj4^9yFdH{xtISq6!0p{nmT}NNTr_v zs=2w(&}+S%ZenaoZ<5J(W;|TYA9LQz01vWML&j<85?ovkz>vj zaf;C-5>@2UVsa!fcOK)fVgfHe4!7fGH zFX>fgPJ2^S{@bWDXIqn!EuJZvfwHEZDNv4+_Q%Wgn0U?B?i91$CjZS*HOcg2#>&st zp)aCnMn6_l+OL*e$3JcUCU7ceNZ%Zq0bd3EJk>X%GHf35I0MgLmp{62TYC#dE7ym^8^%jxKxD(i(g3nrPhB{*%Q z7TTOc*D+r!!@PJhKFyglOLLM`0-NAEGj9;BBGDD`82)2;x6<+{=&Kd3d1@hutXk>Z zvxRDj=})wjOaABfFhzX;v#jx-(n~3?^$L9~w>_|H(in{=4EBNM-F*!D# z&*>YDoRQsOj4aEf^G1p^lHH}};!p|FlcV~GkxP!HoAjmGWPCzTK&f~VGE}*7Jq5p-(0A<51mz)XWH}P2h<*^a1tbfJ`YZKV_uzNdrnJ04QX4wdj;3nH@$p z4&>#tMm(Q_EK(s+01|Vgvs`8r(4;7g7A7VDq_{%&sSI?IOpg?Dc}i+7zpR~AP+dXW zrI7>)4#C|C?ydkmW><;!**i(RF zDcx`yAd(%mb0J)hen7jY%2DOHdppiTa28>}I2+dSNv0Lz^97_OvD8Y#t~!$J!OsF{ zc|=w+%{&v0-YD}1Yx1!j2Z1B9MqU9VS`w)5ryyJsT+J^9H~)-1qvCQngfISSW1uM` zs{`)gh?K8upRz~T*=_bPWU1!zo+Vhhc+j@Q+DIDb232fX1>s9X;?aaza>wICC9g-U zsgm<68dsX$`919 z!Ac@dt#DanV#6L0($VY~Uq4tRK9BUq!VC&at@Q<06zad4jdyOl<>ufEI2iHS6< zYPDW*_2rVCW~cQh3xMvfkdCWLz1DT04KmYG8Fo+vhf)`#CoVLAKaWp-Utth-Q1`QO zKbK%j?1l71o|~gXdMo)yTn2mr$X|z4;O9L`1C&aHC8xO<`W&`@2d$X&A-aj@mC zgF?M*U$;}8}IKTN2jlCZX6WP;vnnC~K;R?__RTbV zUV4B7cVwPKRq*!`zjVy~QBm=G!t3y#-Z*!xInbRMI_+XxSw$IL<)UAw`-7o_$f`b@ zK|~$d(_1ne30u;Nc%@DT#Q_PTgL!-!mTegljwv@OtHE?}84^Va!6Zk)DVd|j&HFM7 zMVc}gY|43TAv@v5wpn-3HtA<_0iMwBBxNHyZKXF+znu6AUeyJ7e-YGrtRVnmT%i|P z4UFfa0_poQu_mLw^qOXBHs0Zb8%(gDJe8M~ssfWhDz?mo}E z`piO_R61s>9=t$b@IPH8{oA5K&wAY@!t=7F_SN>xwE`QPh&m4>il)Y9aghD_$%w{fnw>&n@F^9?+m8IUiIjow>tqcx^)S43D?)u&&7Rb^;;_9C{ znz+Ok$2?<{r$@8DQbP5wd3Zcj{&J=rY-K0%N^K0T{CKl&wNSiXm*O9+%%5!qZAu+OGBuQ&N~6JIHOP3rQz<_44QQS%;Q+^vaL&BOlm8W7|oX zrZ0+lF-D=GRJmbq1c<>Qz4yJ1y{rbc(+vH=r@CqUG&` z*%@$p1T5`A5(zosz~~pu5jM)yDE>}}$gcxZG!!FFhPDzphs}EiE9g%0Nj|6)+Ve|V zGXlMKi056861rKp=RI5jKJbJyFc(vUF`Om6uh4j9C7J(S5SIU0L0CvwIJvn0AD4%d zm6_{53Usas@2tJx@xIl`mOvjJWt~MrA5_Kfo=UkJvfS%$%^;y`BJE1iN9vj3G0TrL zfmkom^ex6;I7%JdVl63gqM-D!mmas6pTx@`3kNSLMWb-Chm(N*Efj_f-#VKA?ZU?n z02;8ia9nlb-~H(PczfJR_1YpxXD6f0^945yFI9>weXu@x6^t;UwWd{5Gmf5^4gx1% zq2dAA@l_Xk8&8$6;YCCgj?`^|e7xNZT``BPPWdJ-f2ZHNH=AxR1B4*CnIL|?cOQyi zBSB5VI}bH?U)?nd`B&|WhIj=T~C;Yj*SmNEP0G;RZ+3cgyj*$Obd4%4*+Ki+LF((K^Ipw26XYlP(IWWM;|_B)%oy$WoGEaz9b=E` zfNT$uc+oDXDScJ_>+f59a~QugtlQ$hAMCO-IUq}6o~dFQrs5K;0;;BH#yP0@{z&t- za-7qkq$vi?KH_4mB_+$9RAtN$+zYcgk5~Bh+x|gwVd~B=zSfPG{L5y4eDmLv ziZ0cYmBlBo|5UOQ!w$XwO7W`A&c)ROi&~*tFl>?^I}}W95}=!2PaD2Hc_dJ4`9hUI z$3aI>xkwR8J^bL6pVhWowu%uP$bI2AL_ppUbM_X7;>$q4cuvw^DzbHJ{9{XvH*3S~ zi*d0eJ-sPUM1rR)?p&ZZEAUpcWOwRv9%|b^b@}z3_e%QsXKJCN#`%MP6D&`Kz&r9O z&O5FZ;btMB#CuL-ZrZ5ncB|P_jqB<4Q1~WOGpPs1nL9*SKzBepam~lx9qG6_dZ*uA zzI9e-ChbmA#?+=n_GFGwyt7)d)Vgfxzl*YY_Q!DyNmqGG7CXs_gE8fQ7qH6p8_h*G zjnv9|d$-E%%WNa5Izx#}x4%luvIB8yB&;xW;o`Fw!Bm&4C- zU?nd*JF8-WYODcimADza( ztK-$2z2j8~@QOfE-tI3xR?kUExfcn~MWo!R$=Z7o6kGx8`zwGdUx(z2*bPapM?pgP zPRLn#-=l>*1;TRSFQ-O~zOSnYL+vYTeZS78ue4V4_k50dlm+-$gDl@!oo;(>RRv}$ zqSILhB5{@LbDBs!hK@iDIf)f?+wz6e)W3vaU&+Bk|40rw|NZdg$4n-1$SgWCzLn5~ z!K=&F5g9(0Jy*HXwu}vonO|alS(^?TaP1!1jhk*ch}yoZf(~e<&HAH@-2#A%N|@(yl+5k+1lScia)tIwuT>fP&dN9 z*swgfw_XOC9f|$*`-yEz^-t>gqKnjp4Bt`n*b)9~s-oh%lggeT(5W1f_rVCJj?~9= zBjnz#v<=nlj~PihlbaD1MTN?tcH>JfAn42jzNQ}0H3d`7Z4dW6WgG9$7)1*x5Aw#6 zMY?9cZ4t&Td6v!$IQZ}EDed~l*t>DZ;+{`X#BJj6#PEvxv*P5&`jFsaD_;cX$+{2x z;l*F-O$_U}Mju_U>&EiLu@g@#lz{zo)uWfY9)E<>?Qr$=YD-U7@l^2LX71+U`P+K7 zG&h@aJp`-{<@~lMU$SGTtXo^N0{*sKczadfE#ynOY|-VFxJ7BfR34wx0j+Lh)gH3( zUX!qGSJ2@hL9yZb?RRZ)-3NhZe?#%G%sMh;?P|Z zGZYTfB@U#LL%tFdoW~)EDdVLZ3j5!j!x_8+Y}s}T4{f@0HEKC=UWXYSME#5MOxK{h zv8)AWh$}MFOWkvpZ`YM~c-ua&fEL`B3F2k4ws@{-h>J(?KiehchHs}RZ5Me%5V24N z{?Ptr5KItVU)_aoq&1G-YBMbyoBX~$ledN)d-(d(mm)l3YrD-@abqX6R38*u9CtJ0hru|a&gbe|OMG&3;U@REeF z3f;30QcNAizAlJ==n3XdD`R^RF1fx6Iw$5$&FOjuD6O_?))!f=HD<38J&-@J@(t&v zHFzZK>=4Bk53?=R_t*C-pITg1JX+s3czEa39DYXVeh;@WY~$7%|6V^prbuZiroGNY z#F)wBbTZCn_QoEvbyHKD+9k=<+iO}$h*cFDLd=WBDSP9^9=pc2!nVM+RX^?&P`p_` zSU)g#V)5wg*%S$-&aLx3689$!0v%O@@NyyCMrdpkx&j3M> zrf9B|k##tc^^$Bzg8PA)mW{#oFSZfxjNA7VTU*Tg5gUy z-nxGUI^yIHim%B8LpFwpOtuWMKG~hAZya{przMGPG{RIma%u{3p7sUo^;n3txwvPL z4gs}S4;4-wY|@d%vOjn$Ye@W*bZukS2GRlhE}PG;1{1c;+V!1CNC^A&YOo?x zWDQzSf1YRfQ_R(@4cW~&xcP?cRoAi>aOEl`D*hxRjEQBdsZT9>4*1%v6{&7F&wH)~ z->390(XDf63490VS0JJnRBFrjs++e57b-hC6ef?X} zx;ZRpa}kp9b9ue3%qQyRTcJkeRN35{>Ri!c+iF5x9j6!wuW)R%wAL}1(LgHqn5wq= z_3z(_m&g*3Pr%US{b_2GrgqpgL^VFnQvrub0LPS;)x_!NX7iJ?!qLtqyYVlAi4~U_ zqIrs!YP=dE0V(&T&*_zU#D#*RDJCIl_$VryMXx6w^%D#Vnx01b-G0&A!h8U1xu0_R z8+{3APqC~@d)l94#bA`(+Om@(1}`i&mC+Muv#V7A#n~uXP;dpA@O$W{x+OU9Os5uF9@y{%*`>w7|VLu4bC5;8B03 zgSqLj%7mqeUD6<9nKnnusKzsD@;*_@)Qt79)X&?bJAqw=y?ZNtN3N#1K|a%JcO_9; zV$8M{>wPRH>Mrds>u#N(wL~%ht<>E-BeZQ}s}s&X+}FU%Il@tS$DT^V;Eb7i&^9Vn zjhLnAdH>s_&@`{Y`BKj2^7rbdf68u-&WY;;WA?Zl(|$!oLxM%Ty+&yY-{dCcE z!|Y~G-7H%~YLcq$5^b?nvYBPFfTl?;)ktV}g$gNO6B%tOi%k_xa!dAhx;C{Ls+v}n>m7?3^Uji|g0k(6 zmB#13Hg24d?Y&iRc#Y~+Ixo1k%2rJ}vu%2O%8a^tH$JoMb&E}Ue$tr>&MEtPYwMQx zxeKNYDZ>}_t29_zHTohlzVn1Nf2rteg!=UkFTu^H1|8Jrg~i9dZQp8i6su%4^1f&b zIbZU#2nQIw?G3?u0ht7@X*n#y1XmEYb5C|{?YVkRQ?HubP<#S(#SyUzzwZN{m)6xB zDBq>u55m9v)5(P%db@LJ%k4Y^RttVD-u|8ysBHgDuIC5$|9QCbgGhV*u3w0C177}py_rxOG~$s-m<4I)W-r(1K?>_; za@}I#xd}qfNfes`{qqoV`FtV6Wl7MX6=q@vL5Dx%_}1|@(Q5KXa1geqDfT??ld+}H z?hR}|SS&In^1g@(FD8UYF~14 z;p>Fw5$O;khwSo^g_@r&wvQ{Ms?!j_?ATj#6tK`>jM1vn&kogcg?eLV-d72e{TYHb zl;y@^9$3d3QM3Xe>G2a}t1)uA>g9`zIsJwE7v12>Ms*jrjKlIXqMeN(Viz6r8X_s| zwMf3-TagW2Z`tq*hEDjm8JtvBLeKFlgqC_r+mlZnf!qnF4R#;V(u1#xGtLk*L zR@wS&gkr_#ZlMcDDR~uNuo-u-62_Zz8;b7oiMA-qs6$|ugp-Zc@VWvCcY>4dL%gDB zpyWu-T@7~u4SZA!M`Un9zgQ7;6#I@iYW+8ZzPJuY{bUs!C0x<#^qfZxg*Q>$ zQNu*OK+T@9e{`QRX6e%jH9QaL2X<^l4S-C=$&fMZxd>SQ$j^%GCr>dOVhm`;%P9cj zt;uFUuo#}=3Rvu>{nS|N=-=>a)1;yzP_N78)AHSMXbsW&%v=i&2TjDB#qJffL&;5C zy0?-N3yX)!v=h!P(7B4j!L);KDDy{$zM^s> z9v`p?!I1ZKt5HIyBYeY5NXYG;JY)OmLl{aN6|R8I`8_ImIS%-^^CL9sOJ2)de@TdF zJv@H6oW1^(*rVU#5zxRiD%P%1@|h5x%CJ|6nvOV~wt(v^uhtXDfal|#C%h%Rs}_H> zW(kliNF-)~4nRfNFBp@TT@GOz1T->GAZTPvc{E+Pu5#E|eF*k-# z{Y&4nylu2=CMn7LT}Niya(+sUJZb!c5*Zd_bEFwC4v`cu#W&pmv6?xMwe+uGK&m}* z=GUJOnLZMc$A2h^&8=aZ=4WY;C>no$@>FY6RCzqZ2mXwz!$87Zxs~ z%5NM3$UpuWZ`*Ef29*(~3LK$Par>5F%E}5Vb&9V<6mxrp?POGu?jG zfy%5Igaa}vufuZU$7n$0R3rHed^NZ0-++Ceh`{rojEi9PZ{(mwfi!VoY&3SB4+C$H_W%S3RbJ0>pG}3OxH{2KcN^082bprS0&v52f zr4`~eZK$&_tnmuCr3zWsQQ64q5v9Cv)O=d@$(p^Re8;U*wWZ}15~Wz?^7=0Q)in{M zCEQUmUzDtbHR4hbF(VZ`jmoHh#_T)O!|zAhQ#kL-8mZ1>mPLYVG{lmh9?I;#vU0V> z9F)+imcX_3d<;o)l}GsCBqsuY9txGad+%6a1B~ zd!(d^Xpbj{4QJ_8F>-O@z*|E;2Wpylf;Fb@^t&$$Px}6A0Mp+4&TPV7VPL70b@?sc zG38Uc$%&$`?2L&HKYK~8cHn3xw9Gi8;mxuP$)e$_XXQ?y%N?DTpb{D%if|xg-y~;a z3lV4;B@_+g>KP9nRIw%=Dp=PF9Gy~E9g3QtuDX<1N;}~>b4OG5^vQGOeOV8Cj8OQl zvvYj%=lrDR^NUq05970L@jGW{ax)uXdDWASP?p_4t}+{AEGjJ_AjV3^O3R1hM{TEl#&L!g#Ne;&F9cgxeKk>VLDQCZqJC` zI^4WVoYog_*jsKBb5vUR?9$noS?vYi{m3Tn`t^sdBzEMjf9_3$FMs@b;ABN1o5=ZK zuxUDbf$R6SOs>Z#LpX(J>ram7P^)vSFQJcAz*h_O))gp1Gfnz^3T*L-*wCzjmG7DFu}F21?- zSWcc4+wSY76mKyy^(TV)n+Lpvge+!EiD-VRVgyc;xVuy6R?1XcXpMeD^Tty=l73OS zVjJo4c}`7F3%F^5AB9E12~CfgXN03Tlx{brvE@0*%H%wOF`}&}c+l)~`S&IihL#7r z$P<&A^XZd9W~MIt9?zZR0)9qj@;R!03b-@b70*dYTj^Idx4t)e5nC!i}9d^aRw*^ovdK*KgEI^{6nx9arwX>r!8Czg`Bdq?6_+TP zY+8=f5J9lmlb_;wmDfR{9rDHa&w3?p-aBB z8$Rh+@w@D%)X}0Jn?ur=_J0MRvR*AOf3u3IZn(8wrdZ=iA6Lc7ApRp56+xziLq^nx zq4Q5f@D5ZHRYe+r!%DA%;r#hy+<(^|N+}PmsgGzGLP+@gc<7goR0t-cBljrMAba~B zYP`$InoD-Uw@V@RWWLRHCCz>4;|_c>qB;?IDQ5u`DnC%a;4%|5Z6;<2 z3F_R-dsufLMikvX5nDf{64xR42IB8o)FqV+yUt3EUlD0U8Z3r!wZV>3vlI6q@T-ya;CB=Zr`3i_* z({+_4yas~L`kX2I{MzJeR3q^TcqMa{`Wtv z#KP{gAh7O?aL0pQ@?u3D#9MdQ^;((!K?jQ1V|WL@|IA~SQAa=8SfVZ}>MJHUz@g}) zux7b6xFybU!0ZV2eUb^RQTGnLdkdAX{Hy7Qa2=xl;n3;j`S{Q^-@dk=~7Ru@SSZc46r! zVN>+6LhSj0k-2~RG$O-v#Qi#4eNAQMV4EIvY!3!R%6M6+GF7TvhPslrih5jbY9^cQ zS=!kQsE(Cwc1}q-fkBcSLmZJfg_&KDaghLxh?AMy-2cb)*4Tu({h|ejWwH`!>NPvo^T( zmTPlkv&@~yl~fB!mJ7jQB4L0?rN~jv>G^pPm>7zJZI~jI({15G(8}sl-rWtYmaVRX zXNH}ya5xT3si7vPSefjPBFcHiOoNbVG}n^1cw11CtRkv85ug7cHb&CN{p zxW8;J&j$xw;+i1+#1bpkLVHl+|U4l}1at$0H&@|i~J<9$yOZZ6UX%_E% z_^@kI1flu+*d!)bqfxg>4D+Wuj;G!$d@pea)AG}HUBsy7=>DRsvL@cGmO<@ALTInj z1&x)b_#fQe)Kmk~lM?)!2pd!7#EFTdUNU`u;nTdTJazB>>$C}m1sId$m}2XLJ9f*| zxJ})ZLBu~6={FINKV`OBV@Lz-u+Ob1=aDnTX;r1{J-t31+Y{a6&EM9{8Wqm)_3M-J zUZi9O7ST1OKYOXCdBz!q#}&Q5jXi`dD;aA#n#4)b9C-gj*VMuxG2R|YVuiB9scGw% z)&%_^4>klND6x+ZpaqqA&GsM&(r`p>f{#I^8eNc-kY~4cGB+;E6exA27gA&Xkj*xR z|6Zl%)U7S2Nk}&`TvG!cDQMkrjwH^f&i6`~2yk~XXf?AnW*G$Gyck0r(xPxgt!AWa zM5+|5>oTNdmP6@V2O6yBmki%bvD4~qsjwm&&&?@A9<^&ATg8AtCcBV z^D1|A`J~^6t%3fm{cImi(wUZ1=Hx;D0@;p|qK?L2<~^X0O1jL%W^c}Bl9XxxFlNql zd7-5;vuRMl!<+S)iW7YX4*6ql-6`re|llL z>kEKUYSHE-Y8;B<34@inSJWJ`NKo#%v;d4zFw0Y5%7{Url#A+^)9M> zVw@X))JFF|ulUYVyIh1k5THlIj<;)~lw@FEWTR-p(+C|Aaa=!| zrUaaki;gV1PD5+&uh`?X~{In;qo zjm1pCcDwemJ49ztGeA-6$_zI{3Pe;ivgh)v%K{mhZr+@Ql5(@@I1rG$J3N)MWC*k< zxvPmlM%5I@6IU-uNLhz}n}o%5eeBfFz_(wb<{uX|gIQ(nabx1Nrm^@i^0!ekcTYQs z&F5ul>C`EF`Mi_sR%u(4fevxbVzuv~vVUc4#KvWCcFLjvQv4;A$fY<-I7;r9m0XYO zzf5Rh4EK`&XHfVi_E#r7wNv=U_y3mEj_;pJc#=dXvlGbtkYzgj~=%hP?A2WA4+mOwO?CuJigyr zay&t_oI;aghCUo1$u40SN^wHTqJut1p-3IBDLF4upoy+3sUlgRgpQd&lPa1{Q6yy; zK|v*5pn{%Ap-2{PDEaAFahLoqS)hRaFJU-Qw2H!!f<+G9h>}GU9YhgN8vb39Lb{hM zoI;X9%CLn3oq|OL{W<}dC|W@gDnSN7pGg2Fi2k7%PXHbjkn!Yr!IiZXDtz%b>t*OE zhrK=_=f_~)ZAGia=rM|dWj>2==iK$64(z)%?655`vqcm15faRfJQVvpx4AcwWT5gl z*VNOtmSnb9v$an7F>&Q;O>695W)TcB_*00I2M*m~{au24K7*3+pyfiTKHRxiv1Kf4 zE%7}#*v?)6w<_}EAEjr8{F@qlMRLb#SxMonN~d_?x*2&#(ysHt#APEi?@jm}Zp6T03Ot+D{OhOa+e6%_m-Q^L_zNKz3-#*C8%%lo?PD%!fs zDJmng9LC9N{P__{FiIA!(Vrm3+B+9H+p8R@)SDPdzoGrBc$LS9No`8@GU{RI^cd{2 zMOxJ+eV%kZ<6HGrw#lBYy#UO1^)No^3yHfyu(cvIO{|6#B~iR3Oo1AH$5O|3V&WV* zGcoC#FTsWLHhIJg@?&lrJmLa$yFO>czfT@v1JrPJ4DQ%Kxi~te&fzn$QSXCCuz)SL zw&5c_05*=#*bzU-j@KuY?4Fr-=*SA7$HF^yBn{AGex?IW;ra|7A%f&_vrU~NW~j3_ z`{D&nofBrnqXdobAVC;Wn`U=JAU9k>vpZyvQB(}8XXXqVz>dW;amD};hC^t42LoEd zCDd=ooe>0h;kvkaQj&KLnxlX=qFh-{4ChBmg5slR=1cB6=l8bW6* z0p&OXqvn(#ahyv1`OV|>@H=MEepCvJCvZjyfWoTTdjtuH#APsa76QHCFc>%Z&v*lF zaVAXI!)B}j^*D_zmL~JPCFwIV0NE%!Tn^@po|2pyXTTiJ0!x{RN?%Dve6k`YND6=% zHHw?ek}+!j4KxxZg)3{w9`M3}G# zE6NmmF)FcxXs~cbhR10F72S*Rk&h{&6wQmRP-pc4LA*LgY5Z}Da3FnvNE8e+E6X?I z?|&tZ*ayk}v7Jl}SI@BzAG000bNGU_hMIVy`c zyFR`lialyRN+l{O>U-2)lyQ_hfPlOgj^1bZyQ?S@7z<1Vh5@_vyYvg8E}?dl`ii|0 zUL$~M!Qa4U{qn#upfr#e&F|N%{}Yh|+BG2<3ar)d(a!}W>gVZS0#>7%q3Mxz3BO`q z^MKj-p&=!QCkDvoAH9z(MEvm=~4 zs-}W3_%H~_g<4IHO!C>TK>9$|hE`4bK;la7O4^2+4Mf%n=|-x>sD-|!HRJQsG< z4KtDIigx%fhq@EhVqRnSWA!@$CxEiRXrLJyKI#-nTkC!bmX80&oLuz#DcUKjJn14? zjwpYCJHa)MA(A17AtqSSru{>zpByd-#o|U|uaCon>E>WuS5lWpx1+mwg>58pYp-=K zvEKdp*^IrF!SQAIJS)>Wo^HjOWWy({4bdPTcNiatw#;6E(wTRP{7I9s5~2+YASW4UKw`OQh*fDx}jSAK4zo9?x5rV zOB$QvjLO(JZTiQ~WZ<-rPAyPRs%fG+uO)G-V}+@ZVyy{i87VgJqXG^10dHerV`YJW zWMg4Ln$KWU$-q#F`uy<`_9~Bm^>GkXW#=GK5vN*#^u4muCcjdm*)HGQ!CUkAce%SH zd2_HUgpXeC`p|Vt>o)2aNCmNH)c?H%{(mn3;QzS%+`-&Hcj#+gFodCyA+aG-0sb|f zA&McFA$9@6O!$%TGAbWhHCYq6u1H6eJNz{n`0FPm_!d|RWB?wbW};=HPLXkv&;eKroB=8V5kcA7%0*9}SQnttf8?STv{q++T>hr;<<>rlHPj zu$p=-3dmU0KN!G|X|8__+_9@rzh09Yz29?1z3&pYGQBa%Z^=Kryx2Yofg! zfB3Oy_PqWieU{_>gL|d?rE2A}*>96e;vuE80p8pVv3P`@9spyS^oz5L&KKLd++&5g_-@+bUnD*_H zM^3`Wimc>c6hb@Ps&BVu&k{#n(rWeCxqlS8Un?t_7rw{jgfnWVn%_P)tiPrsRSp zJc6w|3$*hVVk`rAixsR0!4|zc+9QRLgJ5exYnywM(!dybMXU=1dpJ-SF82(@OzI7+hO^PHb<){QA1XqRO|wIiw~5NsmPZIsy?bUgAL}s zSXpvtu@^U3d{m0hee_&6JPdzK?0i30Id2fh&bOK+oDo0y%yY@2eiuiH6Jha}iFJZR zk-7?_q1iy7s_SA~*AVxMHDE6BPO{rZ4~ACLZYZ(u!!lwS=HB29GRS-MBpy)quB)Gx zeRV}js-!H9n}7Lz3G3c=mZ0AyGj8T3c+R3NU@61=*x^$~O`CuN9YwZ&mnCWOEj&Di z5WOc|rj}*qjR*aFN3IW=yk(h`oG1N#(Y&igZBQ0l$+FJ)cf`R$(2z`X8q7jvGhn4X zsK7ZVFfy{cSoiXn>9Ny6WzbdZ^RiPB*~(_KEeq9%V<1wY^HyW0AqL8h0JrOj$9lV1R{f$@rJM?W2xe2qVsW5 zx@?{8{ByfBTW=Pg`_{4kxahS0zUgd!jLQi}xYMK~E#4^n7%2(Ts?r(_oMy0Yj z`?n)1Ee3$!fPS`{yh2>>X$LFMQwJ17TNZ_hfdOv7z5y=>4Y5e1+Zz|*G6)mr=ds#ixdi{1zp6TGEx9S!m#Do&!%lv7D zs_usMQDl1T1MIibee$sY&k<6IP%q(hfNQE}WJV;dsp3?$L?+Nbfl&Dw3z2V$5CCf= zmKma)i=Lh$VS&SogTTeX+r!)q+m9JvD!&ag6xr3d`8wy8TI zn;NVAS`1~Hm?Y{XNfrt^C>PgYq&iDiXXhWfTH^ESK04bA4!5X~g)#g3W%tr{}qG zS6bb1_A9fER(7pbT4BfU{>Q#C$D_xOp2mA$Bk_QN(kVRNffw8}3w;rlcmZXTv=}Ti%8sDU0o8#I+Ap=#B3ZcE?&mL=M@J@th$BH zN;D0OfNbSD0EqHSLxVWqvlHU^3}X)buVd=Lqo3&LwaQ+E;c|J|Yh&A}hSdkj9pNZD z9*I^_d3noy}c?MLSJ4_^qNg zxzYPwfla3*2H1)t9Ga^O4vd4EPO3)<9!S-SKN2xZgH<)1m6T+D_Wrzus#im2c}(*v zh=zxshwH_+SU^)FU))H(JeS66(jl2kweIuA>|{Grw)bu|5t<6!%>wQsA8U3_ zD7u+6Y4ytWGn{IQuD+sk%++CDB%*ypV$fQ0-TKwJ)o8TIWTf-YaC4IxqK?6GGSj~~ z49}jQdv+gmtrjWp3u7;zpUfR$GvocRaU??pY+g5?@r4b4t3*UC7R=EEr;3L5YBP2u zT5xxDwMU2rb_RRBGQCF3&w>3P~LJu*dzkyFEtW4on(9^#g9}P4S z3S7U}hO@%gA|IlbKH0HR2^8lpod z*Xq5@pQh(@QN;2r@8Vy1onaAI8gM`u;dpzP>+R!yZ z1kNLT)*Zl!neyH%6~0!<8*<#fR0n7=9u&Yg?|+Qhh(lSnHygHvx~9x|GuV%)ltlgv zN9h}~v;_&R&WTu&FvhHETtTW-=9@<^h*{5*0kxOp_7{9+4l}&?+3c(#y45O_bQa{& zSoohtKk+Fp-nOo#QX*)%FNV8pcX@B{XHi9SUGlIHi;u^WDGJ^W(k&k6OBi}l4sxs9 ze)0v@a17sg{_Q!r5;WK{yxjkC%zu1-(0SEu!qSL1KVi0mg&dFT9NW;5eLb#@c7Y__ z*wcxu=bb(FArmHnN4!J3S#O6&HnAPt@^S2|8o4>%9$v-L38?vT3Wt}fKPZS+pir}~ zqAeqHhPs-SR7>u$+O{6epDF#~1UAN_81u8ZdGg>95zzCUUst{Jb`aj|k2sQy)!22- zkFP2D#MiLR9OK1l{A9QPENW%KJaK;L42e~2L+@*z`(eHlQ$!AmBO z8Nq+?-D$q%`im0k${R%e*4bLn-IZCwaPpEJUO#rZs;xahqi1zP?kmXkY?Gck#F5&w6D3|T+2RrVya2uWDfVA-Ieh|@*wXHcsHMi%<~nZ z%{8buqtR9BvlRw7=Zj+B6sE6SaQ>u(a+)W`$xOTrV}`-P$#NGieR0(jbKjpnsHO^I zOrT@-=1L^g!WfnrWstW9*}S3*&9dWb-QA4#_O7z=zk_tE2)d1bsvq7(Bn{pEv@#;v z5cR|&^x~eA6mQx{`xtCEsi54reRQ6%q$F-{b*p!s4t>z+aTQkcNnxa>cDtL-Vf1?x z;ZE%~b#Nm-^D|728a57s&AJ;|$aYoIW!tNd4~dyA*sTI5t&yt=_9W~2XL48cw@aV< zBQcC}Yxn0dCBI_EoXW0tQC4sZX$_yzYIWGT{xn=0yLZvT!*IR*Y57~KH>sh=k&&Hd zb@%u%S#I*=x9ujbG|E)w!*f}0QtPJyg7Y9WY@f4`^+kkWZE3sY2u707QTwNxruV&O zWgRQR1_R=Re~S@>hFiQM8nXDjb`&rI;0tkbip27x$q#J zxAjJN4y%ZuS#Jp+rjP!hPgdZI+QPEkmtao|!w>_W_+K~RH;RMeG^(L!Ep5Er(?zCL zA?}Ph`+$@m6)t$n!I{Co}^$i~G3>D(Up4L6w=tl;A@Zv^A1RbBV5861xGC^0vu*o0>nL?MlHSEGHf4ddEZo|@7Garahed=o#pm9aOs>_8s-wrVVf?(_&vhS^~CkaoaB9s zPq+)i=O0goFtt7}6f6#*O%A7jyKxk?)hDZ){pMcEOdh1A57b!xTkCacG zfO8%h+aL+!fHG3bJ@bQM@ncnwQIRY#-#J}ox%&#A!l@)Kv!*(ca?mPWuo)Q&TzGv> z^aQOFj~YZ*5zb9K0xlcWsUygm)F%U))a9mUS?2Gj{zR$bs7k$g$D7gH zs6zSyK}@I9;^@8YRTj;_-hXazEIDdt`iO3hnXp0I87G28M!2O zCj|_R3!^Q@VKJDCd7~I>n>!nURU<>tns7yRJdb-vs7N!uJ659x7f6g6Eb2ScyZxM7 z1rT8`X3aoRtF&b3Lz&9kCDG6K=PZVuMitQ0c=bt1YkQH|=p4c5s&jFO^VGuZ>|8P` zm}iabaD0g0dbOS6lnR`=3nm859{hIy%1#~I*#Vgq+!7I$3{(mwKEWbF-DK^!U9A+1{LSB+&GgTqcY!>S9a#CILZ-%IXxbx)8-w{(C$9$We(_ znIJ3vvP#fAEo2sjOnLi8<~Ck6f{nZ6?+sXM@%VY4IJS@3)qR~y3=jJnm$#?EmFFVF z<922j{#{g%e#G%X7Tr3f%Lc*$61d>=vKUf;)lXEVI4Ga45E)A8y`XzHu)JRO1UZ`{-8~ z-L}ydjvIvy$$i7I6d6abx;(UBH!b_|u5?dKAjP3#x^+(zqY1h zd%LU|FqNnSDhA1pVW(PJ+tS9ny7U9U-ClnEL8-4J-ATV4S?y|QfFO7-Rz#h4;frNU%$ocZkcq8 zci8=?Cu?FBVU3yRI@3AX&cq|O-gyj&S!sPenFL>zo7ozAmf8l|!Nr;OJ_YA&5U#n| z@8KDu7s zYM*^6-nCCY{_cj@9GJs(*uqVncX9CBW?k1EUibV}DfUR_JqB<5*D z=NV8;0bmZ<$U3an)*$&9LU$>V*y0cDZ|%o|OcRg|lsVI|_BxC8%6l*DEPZNzz54Rr z>q-awIdj>Us`IT@jj)ScGTgEo=nTUYb#VoorJD&iJQ<~BllfIG<3)(!FU}V+Lp41? zg@NF9EH|0t%{NjN-5ktLx;kvr77p!AXwe(p~z-?0DHMDv*JhkQm zRt)WY7Q6dPX%r+x^*QFA_{0d{GR`MNx<*gr;z)`1oo$)dmIjr#I6^BfB+t{uBYu7Cgj@oU z=Cc`ZF^g1O+UdFTYkFgN= zalcO7e?5TeAR8PRe4y6uSAeQrS=DrPd(#gSf*xO*~0 z%i>s_TPoohT+4{e=DIt{Qk6VMr{2BXxn%os&IV+{h{w@rzwX}>ccG3-6%HXPo0{>k zuLKyI3qYe0cl*U=d%nz2yc#vPt5I%1>5xA>dLuU>y;#a>nk7x46g+e=_)>j~uY#hg zdbn3VIig$wOP86j(Lk$(nx-9f79fvPpTFOwcEu@PUz&v?StVGlY#8D;zgxZM7E9&G z`9Q~51x+PeR=!v}rB{z=oZdX+yW=k)>R zzVlSsufF<;w(7Gfr3gJIr*33%`p%^0?08LtQ%)h|79WlGQ?^3aTr%EeJ$!s!}4R=|_{BlhIWcVEV z*Ck6Vbo8iY%5@MHJN*!D^zPNoy}}Jw%1EWA z;|a3Lt}iF2cb(SAso*Xz>R@(Tn?9Vz3kd80%vDli$mQT>Jz!`fbgSTCM$7X)Z2;vT zKx0L|zDusr)967BIal$jwha|Sp*H9-+w;g1n;-^kM?S|Nw-_nYT=6zZ6P@2YSuQZq zG4&_yNatLRj?zJkAoQ`7z#yOoO0&<$@1C%(rnX%^S)Vyr_C3hC5_fY!Ul`bDvCY2pZDxUx0&jkYf5;SVc7xhTS` z?ap{{&__b?uPIC08!YvV3|5X_s$W);p67}8e!nX8?Cga1pViYGod1y8luM*5W8tT- zWzKZC1?mnyn`s%11m5fkDF(wmL|C18k&+YBSn>1Qn=kfU-;2}5TsuC>7E9jyus;jI zMjk7YbNhY{1aIQZNA1N_3?bf;d~6rUiWUg6A8M9;cQ(X(gCzA}DNmJ|o_Hab#Bzwn zKRC9D{sXE38Xcag&CEB-0L)GF9hkA z!P?H>;0HjO+nT~R=-HZLQtE~z?;)K|L&L^6n&PH`p@l38fvyOB8OBS)-DebTaWZcn z)ZwIqd{|8gF|%#vG0<7J3XKs)Y939eqPz6xIjxgiCJLS9{q`m=`O9Bg$GS98rvkMQ z1y>~kMJqeii4Yq``BuvdNWII zoPkQ!;vpst^QG2nCLkNw;*PqZPK3P1tVzQ}4O?TtF$nX(0gPF&=hvx*M#dTCsz#N5 zs_C4TyLC^4CLjieiM0E@dBifDgUb>Iq>u{x`1m2 zDF-6DmSvpZBjo1|Uf`$Mv_Pt<99D_sftgaqNC=+aCfAIaV*8T71K_kWhY~WYeAm^^ z!#_$q_6FuPagwLMUQvOdT+wV(=7RGcQY(Haxb}a{)d%fh}0h+BO9n zPoXiOFz;`udhSpje~Iq&S2H;Mc?i|3FOu~v12Eo)jude~a8O$ftR>ml{@bn$o90J& zKVlvdlYv_{VecBIVS>sd^feNcZKH69Qt&8x8t($ z7Q-iHmAhkHTghV3Ui4)a_prhzh5d|7SA`1WZiy|8=zEzfgc-LrVNZ z0Vez(6kvr0)I#v@UQuKSWyz5&ds!>mi~0(9k{i*~?|(ZhP5;PLBo*a#Ye<|+r>H;> z8I&jO!M)U+oBs@y)sg{-YnNs44l@q+$+>VvIvYe}ole~&2VSYfSv>^NbVZEroSKi* zITeZx25_5%V;$XVWHh%Cqq(ot{l4tNEh(DgChj5?qW)Gt$6BGnlBOA1d=(TJ+!$4N zwx>c6ukd+-`h6t&Ilm}2M4NsWdc=gxPnFwpO^%9Z)fCF@zLgQM?E*0Q>>s*`;zJI7 z!TW`i05_Zw#Xwkq zZnobnY;p$XN{&|l_q+%*!#DNU|07?UECD0SKVR89I1(^${MQv5P+PNJ6Gim8QXMb& z$UWGk6G7yUKI=EVz;gcP0CU&-r9w&+2P{(Xu;mimFq|awLiCFTG~ujseEc%o!8v&q z7~+B-Y8tNt9GBk}Avgd9Ir2vl3I>#*UV#DubF&^ZWWnDR-$Yv9S^~HQu2>aLdb~na z9O)kejX+~FeolHLnSf?cBf%dP{H+AN=JGmff5CrGLsx>)OhdxYjPAK2XmC{`7DEocKB>D`;gm2UfHu1`Q7BHg2uLpRAGDtk-e{%Fwe-t{5Q;nG6C(cm2Mr+ao31kUxQ$wQT?4;XWc7#f<0p4D_ zs_F82eaXe()kq_SLx+9gcj47sa2p-^8;uCXah6ju6JcBZkRFOkbGA)s37)h}TCULL z8u8~m?l)kG=r&TlL478l_^ECa-7YFOZg~hV2NN#QYilATGZ7Y_eqvi*pyyJ>6@7Ml z@BZuwi4iNv)*8~c<2{cas$ldZkjGfN?2}qODOGS-H6LTaQugbRWlhBTX=4GoPJfcP z2zlW6Krwd2#=@?jD%NZOxWW=ugcK$(v$U@hKeCvnnU0Ab^_dwO)|iOwoz^cbG>+!- zCrQa>`H85-LF&pMEw}1N_5w^%aH$+>J~?NE#_--Ci~i!MHI9zSa0A`?iEbJR+l)6M z{3imElNzI-z@A}^P}NU zxOh`cEQ%9O?u#}XC%JNLNx0eNJ5h7*>`3t;MBP+{sKk0{O&NFc8IM#)+}N34*tETO+Ur{&uMvFCnGhwLN5&2YUxT|}thtcyF!eecedDyE zwVpwfJ`qC!d@_WL2tfQnd>NE@?^mkd%Fs)w3WDEk%@u)SrOm7iN+DSsqxIt+bUa;3 zNk;abSyqaOrjxDGQpH1!1mo0M#+r?#25mxwya2uhkB|+g%TIU4_Jl zXfDDnxPDPb2sgdQ13%B+iEF<%HlhG87R>Q4VeshcYx3w3Jye(ppfk88h&E=cI00VC zNqp*C0%C3rkrU5LH7h>j)Jwx)(-}gIoP3^XBP!Zk7JNFqUt3m@fRS!E58~M_=9jCF zZn$5#TT~xI^I2ULA`+#Waj9~{0}t6Q#yFO}HXCsY8AhITP3?1Go%OQP8_m!9frgo~ z@6V5vEn;2^j%!Fb79iifjF<+&caz?8hT)Nc>#@S(`|n0-HjjSCV2>uzhR3xC2G5TYsFKFXRp!t1HPr%B+NWjLyNT5wXC$De+ZAie({x3sC zBL^ENdqX1!f`3RnMO+=llpMbaJpb)XjGlm*<6mZC3k?*)Vr^rJtDJ&Fr!)b&Z z@5aGW0n&Uqy#hZZO%0xA!5jWh)2qJi1Qe&%T zN>FKpGsH=2?@&s})Kr-=ac0y>H+{$ZJwHsy!S(G}KvbeP@kMZo54=yZ;wk?30iUNw znnXfMTHzQ7+2%D?)Rkp9#orRS}E&qe-;I-@y*x8sOnlPyI>Ct$>dC8?&FRK|}wDyCd2 zu_&wntlW}~@w&kueXV%NYkuP_TO5%xS$(c-E1@_)gma52E*bw)}ht!T)_UUi|S zmjBXlGoJlAw(Hd5bzq6@ArKF+H;yrG%|h>U(XRUrPm%3gZ98=`wi=~gm|kSHTa6tG z5r-xiNC_{NlMV3#LtEXD8kdLcf%gomV)#YpH@{2T{r1;ms z-jplJ*Rv3P!nVN-`JK~^Q^W+jnQ!gU{&e^b)2P2J~zMp&b%$)9i9EKlGZF z&1b$&_wd~BFd_Y=&wGHS(v#Z8322|suY)#~nM;ksnJzt#50>Z-__v+pmAVZs+%5{ek2O^c(U;hV3pJVFpQ0)H0BtO(g-_O0@az zaV7Z0HCkj^)RStH{1{S6;q=600Oxd1A!(MMNhGOIx3^*X3e_b+7f??Fy&jj|N_lc( zyv*=h4@>!9@P<;w2SEymI&;l=c~}_}-_cN-qyl<_83N~5e0Q5oR`(r~nEtwus|Nb# z#eg&6R)}q^NrH5W#zN2;X07*yLc5er8JSXs$g@)$JukwBji0L;68Xik9062%O2f$C z5B~eDMsih(FNv*xZW$f2S6Zp#35uu@;>%abUN&n%{|S9}fy4qvs4`C_4X|&In9%^1 zv05v+sD@{KcHcBz^$1d9#7|&tfeB!3Q0LJ7gM}KZgx4zBUX$BtE^iUHD0u};X1eEp zQPgJ!G3ik;-6x`iC?=ZR$D>MqAy@}Ys+)9qP;pu-_y9~7pOg^QSj)6m60u1h=CQM& zo>Tv)UOfeF?}f>TW!Qg$?7B?)v~07ybyH?4^6KCyJNZd=>hM;J_0u}S`TSnTdd!n+ zrUQm8@kmeEJtK#B4He)4L>n|TDAM*O0#6?@XcG!!B*;-e({6sd+3yDNL18)#X(DV(#Krmo zw~XjlYuU{UU3huq7aVU4s3w6%`&DJwzmSJGPSAyr-Z@GzD*h51Uz--#aBG$Fpiqg8 ze*VJWiop@W+>2v(sDgdicc0e4L9YsTWgKy#2M=1OpvJ?2h=znCEih~rm$>Y5@k>`o zh-?%WzF8$3p?T`~IAk*L8nPXi;jI&2yb9fnuO1b|=6WLHFsT0|E71?*3JWhG10V5k8 zWF#=QOI`tLw7WWGD!b{?nTXs6{DRN#2sMV*?XU$=d)}uX;uK&4Jmv7V5|QJ;H@A+v zAZOEi#>n-9;#m^vz)b>q5+cF5^!~B%MEyWFg(S&l_QA=(kE)d}_dO}gZ2oSahiH}RSwmcngn!mTfsnwz*+*3QnryOL66t9W|Od|P+h(j-TX%h*Gk z0g=}ZGRVO$+50aVmrW^6ZxK|yb?ciU!lAmIL=DKeRSSLa;c`mJ-yK`X)jaweq5Kj! z&c9UEPmdC&R>QWa_+fNztsKnb!EY-%=$}qp;$!lb3R2OJG97HVHNv|P;SO}eJ4b`H zbJ{D_J!g#0F$Sbm#`-QQeU+{xm;~M@*Nc3}2S(D?N#iyQ<XLh(rB)ZC6)?=)>>x=kxsIzs2*@ zGj6c=@1cb1(?-~*ayTBB}}~1b_=%@L}ZNruvsAp&6;>djeQoPhx3N3Y@tdJ*@fU1N9|@MEd#LO zcsX+PRz(XdRe88%mAsO&NEyGAQY^T6c{(=gjo3U&rSIM|Fy$ze;vF=6ESpGXTpuQC ztfXTGk*~avX-Rw%gQnHrq^OM-(vSj-5?XeKyy_76t%xIxsBE^sE^j*7TW>sP?-l9J z+V%}kv4AdaARQA>y40hL^7FImouy_$DV)upK~3I|aCb#LYqWu!eG0RVL5An3MoT~~5fI_+5s$>}&6$i_97O8IPlGyY4_4CUBvqcX z`AIdK!RV58-7;}G32&R~1wQ2OiB>`SKTsda4UHjw1JDR+Uw314wiJS`f)pJ_pS#ft ztaMj@Fdt&Y2WHI1wi1*n^~L_q)3AIDD6E+9z9OJ#1A_3&zyce|b(W6>1-7E8@tV&m z&Tye@I87`1qhhAd<5u`*gMgI(n3UWSNp2iWzv}0H{=L`Hx_f=m_}ccQ`J%Go*XlG% zKlxcP0o*)F9&~7?;PXmfF?WjU0<2}e-$5Rh8nE#WA?zaa)!>A9jZ7E7Q88{>p{+XW z+^+9D=-fUAL(;rk^5yG=2H5()VWs~}t@0mO>0fB%|2S6qcT`08U$N4^BdCAi(EkUl z#Q49#O8?_DE&KnHr@hctx7ly`#!5BQ4!%3LyuJj!YfPI*py2UOzuNhIWnw43AOs~( zt!Jxhl#2?gFkQK`Yb97>h}7Rt6HotqzUJTZ5uRLLb@O~Yl_k0sz4>o_z1%PHIetwR z5w(1-?0nIUifH1gYQMaWO>JBQuDW?Y?(5IJKXk1{D%Qn+cPY)j%+Au4%EOb89@X>q+bDC@jz>s`XDWHjo!iVBT z*A=^)+xqkLzz1Ujs+!C!b}@$2$T_93<{d2&xZTmv#=W50vaBkcml-e7E)@i~1YI=I z_+CUuhjKHj>0@Q~?2F1+n)uf8JMzA>ioUu=UU8q}EVbHdg?*!yNv}b+0GiDiui(Bn z0~OF%RxWNXvXx2%PV@5=(3O9Hu}HBmgs#j(&Vi^6Lt_ZZsFP7=il^_s`v}ULJAV(6 z?xuQRoSLQBcNmgiVS3q1J$x>a$x$!7Ga{DsmpCt(k@?eV*fI_;Rh`(h$%mb zGt**?F8i#OeUOO?pj^s4<8kpmPyK@#v0_dwWi4){?ITp&A!|WO~HwPm}J@ z*OZm=NAl6eSQbO!&WoasH{X-?pyH~nU8ZWs-{FviRS&XTqbnJq8<2H>Qoz35i!RdM z+;Ker6I@pw0l=3U-|5mhN$<$CL<=#^u07cQENHMjwR;#%C0(b9zA5;f5JrVEnYS_~ z%h|xogwmz3iZWdDMYcz6cFoKDjKh4)-r6$z3DRi_yC(BO-b$Q9n-?04?Es$JrrX~h zW>i<;ZQBi%pKB^NlVb}>eIrp!-Wtej+qLJp27=!iurzQveK-ECE8EpZ-Iex}!19tz z3bA?x_}2dY%BG4&1AWtknfa0aJ>G-xV*TV0>0|p-@Qm~+*CkOfWcvk0e4NtSeFhV~>$--AH$`fi`~54AwX)>_{xBI5wV|d*+Ch((^ zcF6o5ID^5Cgf?0e}dzJgzox1?~Q5do68gz&AJ2bh$;^f`#T}+&1Yp20iSjEk5 zpdW2GDsAgi@{xncL6>9C0AHJJue$@YPPs3dymO72qp`pf71ejr!DU7QKFTvYEaoCo zpE?6Oa%bRoB54jW7Nbz5aE{yjdCokn5v!82&#N$(?|jKHr-OQ--|9n(QE{gQfKMT9 zFP;{MhciP`%(gEQ5px*)j9?wc`hK@3Wp^n`7isiU_j7M$U&=UTG+MI-GDTX2-AwiDv}J3)e8<6Z!<26b&nqX{76WdT9Jz3OqZ(raOFn>r)A48Twv)wQ+2dV-2ZT!x#E9q>gL*V^N7dxl zfI+3G2MJw$9bwei=7p;kBvCQa5ekYjs7e@xVVxN|QP96MZT`M!Tak5_QrcT|uZN8knKmJE85p5Im-YBqKW zXK62XUu`(3^32`0^lh!91%@WaRUBo;?~1eub=L>fcPPLJ#H>1J1Ng+6NtO3lq*N}n z!6_Ky8ye)5Hkv81TGh{yN5U6}64T%T_#5K=sAGlI($5IE;m(E2zBq0ntSiPO zmNXAo2@}eorWg!KOiO6+PLObY-S}CQzDU-HFCi^IplVtJs}F2K+O$ zl)!DS-YHy~jLjRu(gg@|GIt3Jn@lOwW3i{;1IX_YlE(gFZh8Y{!mp+Cj2yL#@529l zY|RQGp3Y`3JXD^}MSVr(*Bk9o57Kl(OqyWYVlj}y(107d*GGt`jF1asQw(-Lw&i-i z%P^o8+w?cKXy;v$*}DSE4DzpDG$?9xwAE?%sK|o8F*h?zgYHjuIIY`1M2}qUO@w(f3b0;LjYRwt3E0M%c@wU}g z;wGi0QS!HgT^-vo(Er?;P6@y$Hzvg{|RYLRC5`yEd~Kb_F*$sE*x~0ySH%Tv zw;D?^2QOMr41XRsVOWf_I~3o3=sVAN7U$`v1b<5QLKNo3pcUr1IEOIb&lp9g3+&2Z zxqI96Cq_JAjURAe#LtQONU%r7HwOGUrHA5?e1(gj02JO5q;CJ(-G|uhFqH)$(BMUIK-NA^8KV8Z2GdS&7 zei6o8Angl zaLG%htKg(y7kcALDFj9&@C4{IH_S$Zge=hnH5z9a4me3LHE-rbH=E`seF4tja}s%Q zor&#jeUw3Gcg@(*7#oU1PJW`;dtde~FacW66Th>kFbJ?EY~;YVc+6va2qo+~_2ExC zb%LU>>aFD)kTD?3q28iWk6jSW2luBqdb z$gz2RV5C`Npptj0cOgRp)7ORjw4@^@s;Ll@1Bnoq0p{EMS8IdYjD%aLVb!i6Fj@bo zc7{L`uGw2J(HEUs6bSirkUcDym!vCe!}c*gM%=u##XnV2c3rF~$Z&P`OqzA5mWXe4 zAGWnm3~O8o*a&?OIR{c4|jl)x&4L@w+ z8Q~NZvE#2%3Bfb*uZ1M#5k`ddPvv_zXzN_KbU7hXx6)`(a~_Jmja_5woLQ-;RU{D5&+;>=6mG zVb@2+L1UA8?Nep5iA2Bq8h>J^pcTq8uJfX~PQ>3=Ib{zkuXvd{8xFIz)NY-lgVit4 zg<_xtR0DBik#P7}YUp`d*>3HRPYn9k@LC&47Kf$T@Q95~O@Z};D!kS3E%A0^-iX&& zEE5myi%E*CaiH8JeZB7szxPW)NDu85ph#5Qh95(-@vJHUhCO}coIZS#TLE1EEqm~v zTWbCzd+_gN&HvMt*8e}V2TcE)?7=^``cK96|4rwSk)4g@f2p*tMej2sdgas%GtC-% zQR)5)?1$yz4iNQs(Nh)FK)n7!cFvSNKgqOGjlYam0rW6hkX75aYE@I>bJhL4Im(Lk zX~}Kd;^lk4ihnx^mxgK07tV=lt?r1Lf)XQgF=q zjHog-^ExWJC?v?xcnyUXp`DR^(YjZ9r@)Ns%pdExA7x(|5bL~huL?!hJqijHTNU)M zytz5p`KUiGJfR7Cj=9p|{t#|d#^zjf(|bt)Wpk-qoD&}w*WmYq-UQ>c zKu;}N^eHX4#N3~X0rsR~do41_*G;Su!}o59QezLRoLk9cajrKWH+9BA^MdeHe?s>f zjO^eUKW9Vcz4067Ku+rW(i|HGSD#y8DHHme2563NyM=Uzd@MLs)@YGa*4ATKctm?wv4|ZipPN8j>6IGKy@2W}MfdO_$3>n%zM#_2uEQ{kfIVrs6ao zS*6L7ZAPr2!w|cX_`w7uI3BUjXME3ZGs-hV6x(c-ne{}>6u}m@fo7hj$%HpW*N}By zb+6&}bLX`b^qS_E1@_g2@DWt>PN!}BM*}(p_tVo5#txQiz&9Zs4|3U;2_r!1Jg4S0 zxE(`DP_}}QXd$Q)#*x6IpJTUhWczAw`;afI3&E_-Hlyr9CGbgVt)H* z<54tN$@hoN5o~qFKoZSeTp@0n!c+kZY++?Q4DZ)jID_~$b$IpPlO(R| z-<4zw;gO+p%JsJ?f5=82`rtoLsCzHMt|K_~70rjo2aDRpCpb~7a3AIe$~MdH$5b>F zkAc544A>?W?9)LW@X>t7E-MKSI&9R#eqy3V8j_Q?;F_LKAFVuQP zmhXws;V>yvsU6v`R5+es#@4PYUa6NJcW{E9;BX0Im{ENACAdt9KbfkP@75K{EP>Bl zQA5ar3II6^GQR|p;zif6$s)5-)ch5Ee!d^juqvac8>mC;1NwM_G@dl{P3fmr8)@yJ z-cZ8po(oN}@u4M82H!8uj>x2vovNTdHpByL(vv+Rh-}l#C5CDkDM_JNyTA*2KPi{6 zH_r8Cj^kzGLFNCrU~Bn!&og5ENvuB5_D9Bi;B=&Ul-LtKHK50ja%w4Ya2;vV_Xge9SNYFz%PsFXYZPOpeV+4kawBb$K%!ggY2V^Jh`?OB zCCAwOnSsDA%v%*Y0U&s$yhOClndsy|cLGwGZn}{7)I;%BAg%-OQzi|W9roxp{cSE; zlB`+QXh$iy>>tSTX=vT`;WgerNvItNZO7fJy3$%@GjiUVE)*eI+)!>dM`=qS|Gu2~`*f2*|K!Tq37Fmw%(@c9w0jr*5Y6*DY32Z_6G z8bw3I4$Lxq8aq~793;PMK>K46BPDId#;JY4*n|86rHTRrx`!T8B{T7anqNN$EQ>q# zQ4PY*$t|ZaP1}3i`Nh)O!*q~W83;tQOZ>P@r0tp#(TX2Mo5W@8?boPPslRh4rE0HJ zpDdl($gMJgi2)s|tfotAKnum=&R!I2xD#aWYs=-4w!KSz;smM$=&7Pbkez~AhV*gy>vFyCF(hlN|%$&SN0y8?HA?k7j=KO zA5#!OJ$DKdE)Y`?NSrhi9In|imSBs|vzzMRQzc^#qGITllC=VfkR4I{=|3D>(ZzKF zCOE{=AI`@3kLv9O^_>2OLB0@f-XWGo?fb%W`Pwb5KgN9$xBTmZLPYwDJm{ITFapW(L4-cHI|Cdm6cEUhJg3pqLw2GW6c8?N2c z=iGjohO&M1(>S$xamSl^{CAHwFKr}Rfa*0W?DcE3%u)o)VY)T!o7E`7O@{v(I=TKB zSZ^JjuPNXlIi(BPH4o}_$-V@u3m(L{XuGk;bnE1l&3{ABCe;g!wk0*n3mp^Nw{tC; z3*8(BY0V=F{wv(XS!(z`sh!UV3qu>c1AiTNQ*LnUFvw$e-S2SguoHc_`$Saa&!EQk z%X`<&!rK@@EWlM>w&moH2|IK2M5vhu{?z+Uz@k-qf45nlKl@Pe6)}G^+)enUqv7f~YW67ZjqZ=^#*6Yv&clG2-jA!( zbpWC9men}#O!HEF^g#363IG7K+i)3$@5~)Ra<>@DP7EIy%48tg-${aUl`T&lyq6k% zn0VzWMb4<`7|Z@A#S4=`THx?c{HgZ!EVWFIF+|)K6#R08`HwIxWY-?4fKNQGqTz14 zyq#3Hy`$b`h_o5P4__T$)Y77lOsGRM&(D^bNGw2(u09yZyMzGtIp+bqOz z>Fsj#iM(vs0xEvbZuVBk0EyCbCe1w=p&e`c8;OG*8j8f9se%sAFYhV2j9zKNI>0lP z<~f45pjgyLPzFmGhie^b5twG`>{!L%te6&pVMaq^NxfcBSesk1_$HkM>cuG0$rn&) zME}8mgCK1GDFpuy2=ebeod2gG$p4?sp3MIn2=dRZ{*NFC2OI1E0zuSm)>#q%t$^uA z-+_=zuE%AUqlsa<JrriBglxi&1IIVni;5egi!c0s z=zs40y0>!`GH(!cj{W&^uoF_##%D<7P~6S-^(6pxHg}OPrMu;`c7Xr+a%jSjNEh!3`aL7m}ZBEwaTJeOdG@IJLDA$hBU<6qJJOHCgnEf_ zV?md`t9v_*-XFrO7-n?>J@B`~o5NQ2FN2^3=SvE{Tuc`tVXV0zfvzL;#1lHm$;hSI zkXE{jr7&!;78Yb}dJwy-RwtDUJ=Kt1K}0T7!!UAYnb2Twfw{P&k%5%ShYG$kuP5c&bU}>jV!siCtn7)4L2!d za>q`{yJnqP-SRB*z5213}kR@i^;9wr9tz>#YnISqMcYM^zb@a)Vr{R~1x zMmuN0bDEPjl=juzFuE1Ae+;~6w zAoaX$v;Jz&3CUdARw8{TMN9#jM^T~Etrpo7>0!QmPC4HE2$=bTK$iIcW{)pVr(aI4 zGt4PFeS5qlh<)RaXJtBPA;Nq=p?RZi`W_X(=xW6Apk?e{^B1xx)G~w-Q&rh)aID5{%zuJ45xuN1!$$R@k_<2J|??8Hk8<`r2tFNtybkuG$5~ zA^8W!vTM;GA?iNgm0ve`ivB>@nTKNx{M+W}b^BwPrWPI<@;+4YMido;hVa+ILHOcB z`9h=PK=dJ#RnFLhWG|{UU{qM=7KyVg^ylwJ;%)xSBadp2Z;8FOXi8@~7|b2G+A@Vj zO3y9nO+>C)eUv_+RQC97(ZU;6yq|~TVPdX3!_n@Xl*sE zl`17dy>vq?Oq60e#wgBOxuyN-&NTcW_Y_37%|JfL%;$3D0n+&jT;k3Sj=lXF=zxOQ$Z0wjoG=y?h~)JfDc(1!|KB8o4MCD|A_39Z<>& z#1!JfJMjaQQjGtLyLXHcHCned%eHOXwr$&5Wmm1TZQHhO+qP|2t*X2BxqZ9SXYbR! zPtu)E`u~^tW&W8NBkvf`tG59NMm7tCgC*5Z5XicOs8j@NZ#Fm~2euTZ8wQRTMJ*xG z13^{T4lL(uk-ArwzalUNqOp-_>=q7g;;@S~s00=;szA16Z8I1}}wx zrt4^*&;`=BT&jwa3f1`<{FxU*?@}^?q4GX322ro;SC`+}usjoH?#=2zRs@S0PRM|0 z1W%_2!Y}RdNTeGZL%ELzodH3mX zyMHgFH#;{LZ>Ts>n(1zkw_oB7@l|o)_lb*~-10OM+!&QbMthy|FaUle_?t&f%~2X8 z_e_$P+??6l>7vPLZoAZDW)l&m`@->7iBN<5xb4X&?CdNBGk@j{I~jjv=k9y{Gt{Ak5+maP*{S)gg4TeJDnlw&J?sQ-eOE{uP#jlB&OK}Vp(sc~= zvU6e!x65nbGTz?ZKv(-8l}$B|9|TJ-J72)-T!BtKJN2b+L4JiCfp4HO%=_9L%Rj>H zkOg0W{6Jgs$H+VM?Dv?{GCvt*(6!+WS?^)ZXtz+gRpzu-6`rK(mL3;f-G6%IPFx~! zJvT4(ar8*gQ<>|VxJ%7^q4iNj%GwP)9)mpEz!T~&1g75NG0*3G0`)q<0b?<};bN$% z|EzyofUfp2_5Hw#IHrhN7kwFVxf+w$iLm=hk65iYn1js_mB>0Q1P}1@dt!* z*i1u-(N7N;?j^&T0r@jeaFIbIS;@lJBnRpy9`wQo%~L~Hq6K-EDsSOf;W88Zs6WV7 zPH-@N1x7N&GjyZXVa60Ck{!BIO>}-FY|{jHQH{3Hxs|DULS(O-@$Q2I9Q9YSMbsb{ zJ6Bsfc=<^y%5_qd*C1JY1eH2KnN;0SMQys7%&0CP_BQEm8!BWR+D`mk(Z0c0UzAgK z1WNw684RO}x#-;Hq%XdPo|UY7Y-r=Qf#K?4rYpfodhb5~k@(m~t(MavY%+h|^#nD@ zo72Ok=VqS4+JY%HElw~~a%hnvYdMp(;6c9|CEa0TgJ#~fVOe1d<<^~B;>j2Hx~Rfl z=Hnq%@e5tHTWzMP*HYv;5*X;|(Xf2YLQzlO&6A4rtJ8_^A|gD-jSlfyW~4(v1af5p zDy5-E<->?ou>;|fmCCPz>ael_@&ZoNy%r!~7`wRe;Ud}ZX;31byJD*t1DY+`g|E%b z++XoD)Kdxo1!)bx`Ef>xxDj@e`W#T^;@<5Jhr!v<81NuJFX_;+D)I3;pj3U(%LyPE zOMEMiUJN|^s4$mp5BsW{I5$p!{|7JTE-cw4;a5q>1lR6VrnLHoSxgj|=H#~o|f-_j^j2QNG)kW-sKmxH|goH zY&0Z#D&00|yWJ#|!LH~omeDJy(AQ)1b9_#u$p(TEDs=i24>yyslA*gep_t4}k9tS0 zKSZrYf1i%_>5T(28%!RrKcS0aZ<>ku3Wqtnm@I9AIrQs{_4|vPVkPg@9wN`^~A^G!qAFAv=d{#)AQkDlri!iRd<5wW}gbm)3rWX9ITfa zIB0}m5Nt~>10p5dXvY5Ys_*CM;t*83M_AcqlCd&4^maJV$(}frte_Z5BT#{U zK<~^7b89a?WV(-4CWD^zu7Gth;XeVI%7NJ)l&?V^s+6TJkZlYrK)D3?CVs-g4D}GY zdGI)<+`1chNOB)!h0BG@=tGG0DDV%FsmCjbRkr`Q;QzYzziej9 znA(~16JPW7eRnPbEyg7#Gltp5NIF-+kS<=WP31}XjS_Re zd+xI9Nl0@iSUmgEld>tsOBam@?-_5SeK_>A^Hsj;u!4Of^hf9Q>pUhmXsY9s-fiRY zCOc(+_;k1P7Ss44^yYoGGj=wet(9hhB|fOGYc)H?iA?Ey?(YVv`mYGq{I{X$PkqhT z{o82X0AlTBal;V4j`~<3SnsFq<_!kYj(VZa{DEg3r<33usw7@jdqVl+SYeN(uzj&~ zW$AO!W#&m?d=)pc-M{uB6l%uvI?4WfDaCPes2OC-%Ad-a>;{K)$RLKQ>SC_Q#$>vrGU#O==@~1(@R;B%L5zN$w#b>^j-QSkS0v`o;B3xA?8yd@) z`2}mX((4R{SPE#mAGk$XzO!dRs+x6q7@cvmlUyU}&NO$3Niu80y7Lvs%@NGnRa;;x zGL`wO0}wv#&|^80w#`-L{zt6fDr7JYiunr4XjL7Uu0^c#R@(E!m2_sm0;$}OBtpiu zW3F#NhtBI%WPC-tb5apfTZ=rcOyn_&JR5CX9Ioi8`et|sV<#r1P21;e%iL78oy%$B zIK)IrkFpw{gSdd+hv$B|SoMc1?TRiXb%3L4L?KY7u!w-}iQ3BoivT;|vq=+ho#qJv zE`j8;-Qb>qrrXTCLAzJ2Y)p*WN0o(+ZL{mNG z?JUm^nv|usPpG{gjkGn$49N?4GhmLZwja%a2>>3WL&a>RRDh_SKjfr-@f zQg^L3!bbo?Urhp_Q@T?Ecp;5^35m~Fz zYTlyqLpc=!b+$4UsADdB8uD01$Oz-|SIy!l71CHLFc=WE>G>C>jCdKA$sh)kY{C6zvUa2eJg;<>~U{aw9NG|^?Rr@Ggp#zK9*?! zFCI4ILrAPn7B$d88H>bp1ge^1#JC|-@*88s;bUJ99be+Y`Lt+dE?#UO%5jGt8hO|KZbcO^p<|P@2c&QG#@<0C!aU{lP zMCO;6Bcf-P!AAPp!9rvEtMLsdXC-Gx`)gnWqnRfr8-V~9a)EjETj!Tpx9j-m(5>!y zJOd_CD|~}&fX_NXZ?uCS4}F`-U@j%PoSR2b;-NL^pn?0#2NJAqNlu02tL@B$1jr^j zP4?ZEXhMoqG+C#oJqnBnlUZdr(~)BstL-v|ieVZNJ;NXa=w4X%2v zvJKlI5)Tusbr~dJsc7vf{=qgna0MT{ODY&i)H??1=tzXjaa!P=pa;no_@R0zQpP=G zcni4bOU70bh{MKu@AX%2(v8yWWGQ-=luHj0N#WqyTaU92O2QvzYtD#?1K`>PjCX`R z%#It(%D@(Z&$2>;l;V5!pYhaDWNvQL)B9s3=6MY9#$Z3Lv3_b0glxe@QsU%gVuzO7 z0ly(2GY8W?pAQ>??u^BuguhP?b3p(jB7xOAk8mP&Hv&xvj!?WDHD+C!>rYy41vH@u zuOG%Nrb|MfcbA6Xs2#XEDPV&_?MF;_mgx;kRV$!ammRyrizP%Pfz=cIOUyzTMF9O^ei5kS@|6UgQYex z12Rk1EXwteTF2Pr_*#*t$lnT$>#Gb)Q+BEj{nDx|B%G4Tc*asM)ce{#2#pwh`n(Hm zx+(OW8Xd{_w?CwI7__jwzAE_isx{X%fCb=uPM#QFhDBGhaw0C%aB1fdW$E}${-k^4 zkrca9tpKBUh{+O_*T;rAM`esSdhvtJbg3jU28f~Wt}v{@445^3vV`=EX6Ork?y21s zs)VYw4XXQ@nlrRXYBeGHdprsnj8u!k?-H(&gIjCOQ?^jBvZkrFipB?cGEmkWi?UoM zGmD}?$OV@LC{m-JQ-BQI0JM$u(zE7*zi-lW+WDd?Ip1ofMpD2qN+UUnu>@+jJe?B% zC}W|seWMVaWO6Qzakuqq9udtur}0(3y@$hUBA#lZ44SK(s2nvA zQV$-#TGu3&Z)>nOX*N~kJ8gc5n0xt5jD*=VsPNsTcwlYfGmAHwmR7~w^X9lmx)_Iy z-EGO~w9B3`!saD?T;2wfNf>W|?>cg~9J!+Wol4Sl3jv8>nQ%9}rTpAE`l5!d=f-*3 za0gI;Cm{nI1s-J`uW9x zl0>RMv>w$Bo1McC!JLX4iODe>(7qloJLyO4b8K|UZ4|t2DaiD0podEJoK$zVhSgZR z3ldmCzQT{#CCv8kw=+GjELT8#xZz$O2n!*I1I&iaqx&>P+-@MOhG~eR*CQQbjlY8H z^0%4+TYjLow*6F|gdt1@ehjmwsj?i#;VGNeAKRz8quyR&J5`*lc#&@sXUO`$0-XZZ%IjRvb-CnPb-GpxYUK)J^t2TB>fiI4AAM3F0;cKD+47UyqPgdmj$jFf!BODTzUf1<>P@OvRf}tX z0Gpf@;{zpPIkq2KE7l!uAshca;RnrwJ7#yQUF3s*_Qen6pENt;za&xoMNa(xL$tH~ zSEBvj22e1war|e|9<$Yk_%{|c=LE3WrSC`3_q5hH3kfE%lXwLL$R^1410U4k9O-=7 zRH3!hG;)c%`AZpze%R>#P9)n|daL1OF@N=?a!hG!>1=I-vYLD9gKz!s&v(gbp_J{- zT6wzio5a@krB+{O-z23BeiyqR&yNqbllLY&;4|ohGglPI~NAXg9E>70ahS+2BzM?>jSL z7aJ-(lIDDC8pOa3$Yeu(MYpIwC=Yp&6;(+%!8O4tj3Ah&RWw%O8n$h`{_sg!-+5MU z@wOu?l%&=^lpR7RcuhdhdX#@r6u1(9Q4}sYE)Ly~NxF1G*(r<1)at;f7C}q|*_wsr zyL2gc-Zm*tYEj*PhZA zz+9{2B*^+&h;+lyqG?TvBbkbFX>(`^#UTwN8-Ag%XsQx7G{f*Y&K)GLNe46YRk0(O zgR0X4+_(Kr1O#G6#S(Rx7@2~+v`A0(DLYGUyj|-_ z_=A9(+s;yQ9M1hqxORQ9)yH!-cK7ub?#I;$@4eQT&*y8qRQ~We8`MCxV@k0R2aZA9 zBYVbaiJD0oE8U(2d+!|>&fFqSao=_|c_QN~37RNVRbA5l^B@n~7xq`cxq9?yw*xR9 zdke^spqtia56q=;Y4)04+JxEUCronl#0s4)?R87jb4HUXzwMVPYROE*s&n&KZa}U!&YQBn zAEvXmd`dJjQ==Dvp8p&&ti(%%GbAF#9Slg@hrJQ#GSazbj~#pBLT`d1?xv@92zl+o zy2I$XbJD>JHy#`6IhbjCy&E%tt3v&SLN$x#R+{tdDNy@LFF&u%4wY2k5K-qRj#Mv5 z9H~Z%qF5b!Hik3!F;G4MH3TfX5L2`{MpeV^Z00l#?+c@G+3IPwB%3Lov4$7*0Urs` z{4O^O@}tH~lq)_EEBCwHTyvQZaGufw%;nxyhUk7uM$Sw^b#B($6AhaAy%#?cEntGD zBtW6D#j)fvdwiu4OjdV@9|xaF&0mIll_MIE2iK{K#ma-kaRVq(qLsPC{>cB zM~|s#vSu;|4fo6s^DH1Wg=^2?4rIwdm4?tG96@QthNAE`N>VV`SCgkw^BX7a0Mi>6 z8Aq$p1UClwOwHT1m)X6AwWG8d&C)aobI{vNccbFMi}ht%EFFH{O!8QN3WF`i>Mi=qYj;VO>tzv94-U|A><)k z(K>VTZxsK=f~u-87WkaJHYeiVj{DUXKW<=1f&Z#pmDYC z*fN-=C6RXmP_va%!dtL#Fe&|p@YV$6eiO)v@M%z_7dwRxzzTFTZ@btZVSm!xEPG=E zCF@hI4cO&#RWLwg(6fF|07guQ{xVM(8w1QSbrCEG)F%G|qt;qd7!zbJYqFq~`eT4# zWX4sz2KK&tMHon&1PT3@9Tzl>?LxcPFU=m*Tis1Zn7oUTt{C$r%dzgkA zK{<(TQc_6SHdOYhavjmW8hAB}U21LW4Zl0Gbr<9*Bv%(!W`CNXb~N$)V|FLf{F6#p}b80R{4cD&xHv z`duBG0z$5~;XWtJw!@RHYahN@*tjwLb}fGMw4px)*hb*SjKb^7pzHJaG82aI$S4Fm z;F(~l!vPti^pDiDx5N&}t08RXKM9f2E;T`O;PR^w84~d#TSAf-X16{jeiVmpes5KvhZd@eC^0Wq-3h7LKp+T zWegR5!}Pi*=I{`Biv%+?h+|;)1EwEb z>z~I6R}HDy*nsp#m}4AxHruMdgaIj6bL>O2`sD=gwd4_PPae!Szi=zc1|c^mw8`@&vrNJ$%6$EoB}G zXRm^2*kU=zwcqxt?&P;HF2;f|qX+}c1;V}CCx{BKQe-~7|0cWvM-}V7!Wi8cL6IYI zzQ@~L8Ug)1JjWU+V>b3|$j10#bSVbZuwXz^6T|UE9uHsNsdNx7@@y(f=4MERz{MJt zKA|{|)TynPKOAd~Z#|}PI8z0EoV{gxkd@g%PTbT9YT8%OizzZi=3v_>Y`iN6LY_<~ zhO4_6#?We+)Kw$*+wc22Gls&bb;Rz?0gaaHa{(3$)YJn=@&sbsx4dsts8AaDJ>YjB zyuL916}n_$z}hHi>LV8&`!ct+MK^Hou^6tC(cd+>wKDX9(i|<^)z2}PhHDMS;2DpD zXX{=Ll>#H488m*&CAws$A|$Jovg_wsjnQW`5J_-@N|F;#iskHNQQd*iR&L60pGC{d}xsV&Skr;0J=zh1i_VJR9Y>RR{)o?h0`gzEsb-;z|x(d?+8f`l-huJ^avEchm zUdWP_7}O+gI(3%5^!drxUa!|64Tz4a@OT~Q;l4a~h0$Pxa<*L9T?Nbp;}hHO!d&Ko zj*SC_aNXwOumcJK+ir`(U*1_OjN;nltsKl!K4VK2vF?JD2E)Xxq07o zb{L|e{ZGyK2A)%(z}+LU$J_1BX$>`KW=&Z6fV4^FSHvT9@KG`j8dB0hye2-QHl67P zf(;L_aS##dv%@{WjctPhZSqD@fGzh$71g(cCMj(l?&XCNH73=l@$>^onz;DSH5|r& zN%3I(e+T37kIByeHRtfZIs0M%uWaPM%jRHWVQ2c!Hu67aKf8Zz?5>ONh|-D7&(+;yHltSQsAy`B&&L`pevc1d_s>}8?9Y%|Rs^iOA$NbY zEUmXtuos1*+(-V|=vy)}Q5wr+6GM6S*+Josn~bC}lJ077m{?=+ZT;})>Eb8(4&-zd zU9K3w7-q54Uxoj@~k!-6VF`~HE ze&*t3>p8Hd$tm;rfxhMYYIYQfYg9E(YQZ<=i2Xm3ZM@6s7`y83WKny98PdV7%E56~ zRK91Ei%}Ye&DmO5dUH|Sh(`FS5e`1J)Jf;mAm$^#&IgxLULLctLCaW?RMYC6{*i36 zAy5ykA_{}`KEzZElP!b)6ST&7H$E(SDk_J9Po~Q>-tDv{FKfvH$Ifr>4X=k_^c`%p zrP+=pMh>!gPiWV`*=m3i_WNA~)##T1XTnc_$HtrK2_)}sa9b|@sk{m#iUER1}GHg}~lxl*ZRr^75EUE4Ho?~LcXB;V-6n)gxrGkbimdU)LfjeA6CHZA3GQT<{~ zu4~QP`a=)Xjqab@KfbBSvA3AaOV6g~kHTNR?90#mk1y5>&Bni7z4)T|7jL<2`Uh|S zbP{zxq9LRHHW!1<9AVM_&3yeVYiyvWvqb#j$T{WUsrL?XLx#&dbLgC)5t@iUuXPCb|br0L%+LVrj~-B zIz>RcPef~$6-vdpMi42V{8KZu> zG63XE9o8W(E2-iTipF{aQu6{(0@C9L7AC-7RNe&Em5s~M1TEbMW6frfFK`w;6(p3C ztcPO01c%~l0WHvo3}9yxoR<^d9T{bBK^S*Uw53G2*X{rZ9$KWtzwlP*zpi90uWcp? z{0SZdGXr{4kevwv1?z%x1S*xI&SBBV$$>cs7^FiL{5T*NgWLdYI2@4oh*b~g7UM2; zZD?o&9~e=!952GX_hD~wbuyIBbEO@~QJ`TQ91~g>3X?Pkrqp&`(U*y(<+;tT`4YVy z9i{`LwnqYXAwXaoEP*gfhePO1pfGsMGaD}tyE7RtFIai9&IjpCx3K+}Mfr=diO^J8 z(WoXOgdwX+Nj;cnc^E7%gYd!#grZX5iS6jkSHX@M4SC*m4L9?K`3Q*W7@9OxO5&mt zpqIfhz6iCiK7?1bG3X7Mzh??}IO|dj3Kcw`xDnp1r9@~-R z;0_IoP{;3BxX?R}7dNhhlsI2I(cLgy>LL(FG|rKXatlWoY_PL^+c2JZd*6_DcvXkz ziXw=H-ty#|5foK}6|Nt|WRix#pqdect`GxE(!XR504$&Z(l(%G5f?BU*)WT0)M#hx zskk)fL$zgD^~sa#4qNn*#+l2ppfybBoyi?3$V&j%o1C(4c}@D1de#u0gJCSFW&?C}ya0?mC}I6ueaP>=I9#CZc6xVHdkwRMe^ACi?35 z(zP0#;P!u0ebh|gmJ97lq$voo8Ue2xhnAe-ISaVP7tVpPYRUTU$4mralaS?215P6` zegfS7e&>49Q3=Cv@zsV%z<~nP#7|2Z_ymH$MX%JIlFfP#8O&Ik$_oyA&My(Cm`%bH zXtgs-x*Z)e8~OAhVPk&4K63apb6pBa1Q5(s@9UOgW5H*7WW83pAFi#S&fpa>bri~^tOb@cR0!G{lYZq=L|T>C;b zOH>xMzS-v7l{Rq(&AaUx(~f%P&%hQ0k@esR1Ot~EiKYrE72`7jYY;k|SB5{Tb7}-?Mw(B_HOgvC}+UF+>8(laJVANF-Q3nh|<*x;URb&F$4%QRT==VYS%AfwnUHxqs`2TmMXCj3@xGM3m%no!44k&K4` zmh)3otdOWPazX3^fh3~P-LiF%OQlJJwu%dlzLr8H>I^G46`)8VSx<9Zi9l=^-jYUf zA3a6A#2ob)Pidc>k}b}&LUR1%Jn}Yn33s2jp=&&+D(3$9=D7WEhcWOqxxIhS<(hf?0tU)=&X9%{^gPcmD zUNEv9`y~{m%{CymU>)%^oi%Wk@-JFY5vu7X#lOHmN05A2^!(r)%QN~=RCB|Qhu#GT z*om^CviK}T4@H9IBf4ChHYtGMZ16e?`y#(6EY^q6#Zr)x`IYUlvZtuvqz{Ui`D4B? z96?j>)Vvyr{pK7;;=@YHt_h&tI~ttI(c!Vg*OK2!4SZTd-eu&QXmEAnkn<5~-AXIn z3bt}vy~S1VP7k!Ef5<2=(=qT^S%;w;VK`#W4F%!o)23n`53t2D?c%@nTzr+bi|wAc zHP1>t6%|17=tWUo);H%aJ7)!bts3ax1Im7Ejaac9mSMRWo^;V8Nx|(hMW4#@9gpOR zcZY;}XZTu`9k0552~s=}(C92c6Pw1-a|yov{P5nfkUL&m*Aa6D@iaM53><~BkeQjc zoOLYR9IUJRjHl_k`_`YIxVZ@0pOn2?+jd~Jl?^lvo$4>fR^?hR983@fe^D|;t9pcj zy#?a1_IGyRaI7Ic%lpsKzgHvlci_~Ru`gZwJc=4h?{I}hJh@F5cY}vtvhg5kwdUHi zmmh;!>a(Kj*mW5OXMuq0Td>yt22Vzhc@&MlK8#cKC$aVBkC6A3G_ASx1+3eCC-~=a z$-k_VGybDwt@Lk@yV?Fx1^N5ozen!=zn8K9f$RR?e*O;x-Tx$a|2M@g$A2Ym|8elY z6KrB;hO{+UN!B0e|z%H~|5V|7If)u#MaL0jF!$All}tu0ZR| zgvc77B1s}m5N$|NhBhT%sFi2>vtM}O^Zod@xRF0B$;$TicsUrm>--~I-Q9XPE9dL$ zsMWbYYRdlgvEOO?5$o&Y`}UQ6=JTWfA;m!EEZ89jbs0kcCj@JFsh}H5dGYmJoeyE1 zx|2Ue50k$0sgTgQTWtmIkjqBIxJmpYr}rP_jdxM!g{PU3C;2ly-`{c6@uIIEr-9K8 zpD5NDSC{nLtwIoga&MkvLu+fDb{8V^<=LI{yRK}^T{y$aUB0Xs24kmd-BUAG=e@oq zoo9V@If&aDia4p*XXd-671JGJ>R)%b443Yd4}q~q!1GhpBFe5F`u?)CRXlBem|Eab z92PKJeJnlup9Ut=J~Z&Ao_M|UuHOVAcEAdSbb3t(Tu;>k=e2_I*4iHtf*$4YF>1os z11aF2qA3gJnezFjptWKwv%R>S1y2HzkmprvMeg*1o|VC-2kqpyc>K|ewtVu_+*WEz z*Cp38pM)(pYjimnpqo57^CN72336}z3?E=(zo5%!T+T&JvW9G9bg#Owr+h4 zylY*5GzZ^r_Eg5~ff+E0YX@e=;rR7|3m(JS9P2yjk6OBGi}6GtRKj*x`m<`~vkM|kW2N{ z6rfNC&%*lzbORLMQm2%smj3HrAChF%EK{zX3>HSLY}rVj zbVP+q(6iAlhH)82eXjq>)2N#ImxTZsSo0la;vo1=)zIqPh$Ql+4fo z-Xwgf$f*w06D5h~J@6Z4^xwxi zylPL-vVnk;JokSx_YB(yk1Jc+9wFd@{VxGqIdE#sW1-?rz;0d3pyP#Yn6%2P;P=&H z%pKn-Lzx?Uq{msERJX}(&vo|*Ldi{L*|S^)N~uI>zfeT#{NGyLjukh8Nn#4&K(#IW z#oI?<%jVhuQTbrXw7{0|L>wkS?|>zQkot0&M}#U_glyo|5iKTJHSiE419zY!V3U8F zdBROg#`TNRN(fmsI57^EU^ZU}`~sl-Uid>D#Ma zcdJKRu;u2X44jCCvY}M~w{W!&M|j^`dYLUl3NG-P1dfkI`S`lb4udY=j)L3kx;Aer z(k1X*Qa%VcSz6?Z$kycXvjSJ4-@{&ZCaiL;6OX*tl%Q&9h7O+umjZl&D3s2l3OcaQ z%QCVOI*`^D7q46v#i;DhUu8@xu-a768c`qllcYBt7DM3)U?@Ly3&Ici3Nm=3fL54JCyMOst`_BYlP|`IhIGCsEH(?V<1zyXCPIkv?18lNdXt*flq>(uP6I8Ient4f=?{@|Fb;B!-^} z5q3b?#KevkgbN5t3na52O0h-x8myps$=W%UH$;*Xq_2-hwXhl}ZSGKD3OU?p9YSl3 z?tm0-;vK`}vf-H{t#TxW8)wa;(R#ofd3jZ$VC7mfpfu`oP_ea)zktRA;YZ*>v6;~d z{+wdlq7!KA03?6rM+iQ0Os*G#BRmFB5RXOHoL&SJ1VZN@q>-7FJ}O7V4!`0Iso8Z; z!vl8ab^8fGO$c3OAAu0I)1~UWCdB}YBfVmIQiDVQi2U;j45ewfc^0~%e3=5sY0i27h1y%b4 z&?`(o>x@ygBCQr?o}A({u4LFpoyZ2~S!_Aza^#~Es&6mc2cyahoMKh_;?oEP>tQUC zZQ{^z86m7`a3L=9NW~kdm-mP=!#MlL`+-W5t2C_(9iSI<;=rK$-BDnH22$wCrXzsz zYz<2o18eU{5Yp2mSy6>U={2sPDJG}yt5PJRAU4wycg5zh*};BHi0Twk2Uu%_X!gOa zxcIQ+E?_6<_m)B#9Xo&?xtC`-!K*DN{my(4~fSqs(&O@NGU(Us5kSmaa0I; zrMm9wVHnD6;&eJk9Y^w0L&Cq72gUPE%*8{Npq|X^F!`P)X&jYi)2CI)YieVcBPR@Q z48~^L&wVwVj&}I%&l^|^#W?Idc~S2slEP1t>Lu4Tfl%KdM;YEA#6TK4IW(?2xuyf; z6CIJ2R^7uwt$BuwF?Z8Rd=qAWC_>ywVUzVE)799D^aen7)%*?Hwm{0Eks2W}l~_0; ztF3S;W{1RgV*1(DM?>EL(>Zuja!Y1ZF>X)Idp*-=^@wb{=$x$FU1Ch+6X<%0LU@iz zttsn3h*x9lVNmDgU9%X9<;3puwZdzgALTRWHM`=vv+h(iX=#F({qlkAl9sy$ziO~6 zL~xFcRQH9xMKv#{iNeWQn+@BavN97ZOq0;j6Dmw;a88Qcd<5N9AhCCLfhWV!k5MhM zg*$eisR)V}0bh)H2icL7t(T+Vdd?dY=IGY3`@4b-CnDxJB%29oVo(p&mM4)-QN%(DVLybn^CCxANn4+4#vdWg%bB%VE#U3#3+oIjhEf zRpe)e6nwNy?^bPv#OeDczUKR?QW7W`x$V@gKci z-_O3!wD7DQ1yWomv_R^ezX0$-o(B%At|LUzPy#&d$Op$LaTse8v<46dtfOYQpJX#& z>zhIE@(7Rz$WgW@X0G0#d$lq@!s{%=N8#E_V~_4bk+hvwGn-)HD`CimG?i$Gd~dKb z_MZ&@MIy}4#GMeQKL9yGa3&JT^ZpCgoK4Mb9+N18|S=o~dth_26>A;sJ60xL- zFRVZuzSF8(v{h>>3p?|j<7OkQLGan#lwVy!u|tC0(T9z9nrOB#Q~yEY9zpm_cUNxI zB^7ut^r2_qB;fb_{_<&e8%9yNQ&T(9vd=3AbIUGj-98{84l*TVOd z_@ECfVSWiMHauPP1HXACHTKUo?O#^z8UNkR{r}T8?Z0WrIR7g{_U{(ync3L?&-?$b zb=PB#Mi9MnYxf%ck5{|_0{qgqae1XN`g~ex0f9&cAAW$%c2zf{%)m6ai`0w(69nZ} zr>DlI#%Q+7_jBPr-_)l{K2PoBf4nz%Avdn@zwU2Kdw;4wz1=s&dw(_uefdRf7H(!; zT0c)q@jC{8-VaktWBJSerq*DqO=@*gozI#c3|ALs&+@r=>K!bce$Gbsa~%mf*nK={ zx*ZhV26Ic6o>$y^u~(mkS;TsaZjB@9?d0+GRZDg8z3{$MJ6dydpG@ObUtcy8XFERQ zydAeUdpmBElwLk>u2)Ox?M8cCR66+vYoL)`Zn^C)1#xn2v}J8y%|~;G7}xH!;XYA9W9iNv6)x(|O4zA}%NB|$Lr)M#$#3-f;G6J%1X*tn z+IgqsE_Yyklf3Fr0H=Vi_1YDd>!0^Hxqg;UICD$bC2Pq|A07 zS7*nDF+pDHxb$MZji}J{r^v@kQM`G286d~|dFbG&f)!t`S+P(qI+g6{&YSh|(WCQqVCsB{D&aH)b6T>SL}(j!`9bttO32(9zAfrL7h zn3)mB9+l6?%io|pSZX^gMv|&BE(lOaAQW5*<3TGUb+;h+0tvvL)K)4GE`w18P_cbo zont96riDeT5t#COqAhRTR|jpy-lLL^z(>pI zS?vuOP}xVO4IZuIUOFZdX_%=ZTzKzKlpX<#|1;s7I!{wTK|*s!zJgE&JS?hcK9Lp) z8%(6JNMEpc=aQbPSz|;BB&7n#0z7`%xv|^^IKk1) zk&+R=%MSngT(!)H-oDtJ7~H3%w9#th6$?ep*&h%B8`047g*3L~3G5kD6}3$$7208M zmYm2A)z#L(Q!N&Z-&j$w=$#EOqOt&8hyqR@qAz3^-oqProi-3;y7_U~Yq!5xot-iC z+-!+2w*1h=8Al1&U^6OoOo-ncizqoNR$1Xg83WfXvt^etHLZzBYda@B1jcVyjx0+}X9l=<{CG2OA`onk&u|IQ)AE)tQI11=P9 z!H&Gz{0-ugj}=-&g7;Nep8$qbRG7j|PDCzb#{o_AcL@_r=t3J3=K#WVoEr%n)Y(As z;X26?qZYH29C!D8zwjr#Ag8lYD!yvm(5xo6|I_KB3jSO4)~=BE4jKU@-xGL*we=`! z8?;5lVjg6cl#6>9*l8jEof8L`0y2oB2iL?|30OJvBmSv<2?5Txi0 z1~=WM$i8z{AW?Yl@{De*9!)qMS|W0GBN9$OV7LT$0Rjz3p+vZ~4A5rMtR+;vuKg_? z6NmidUX-4|AgYv&7T94d#z>EbXKL`d+*(DDE5(ztARE?)X!3ng@?ZD@Hh+26!93tl zjP*<~=PxfD@BwN6Z9r_KarrR%!q4pDiG?D1G!22EDMt4 zQlsTlTgBt7)w-th&-V}oN{w-E-U3P4G6f-h0HId|eg5gRcjyphya7t#p_85I1Qm9`W$-TwWxc1d|Zqs#Tf;KgjKqB>CJ|(^f}xft*~_2`?M*!yuNzOg-3{ zA9GOz@*_D0`?Byg5(6$uy5Wp*n2cR~<|InvCSvZpgEd&YsB?T1STf&3iZ zZ6xc04~ck5ny^%Rl1$`FBXNDb0dS#)^Lyk&lCQ!4;Mov8K-5Ys4MRTN9pVkoDv@#E zAZHB|Ct`a`m~Urf1}j_8WMsByX_Y-k211g74nz%wKUgxz^aaVyl`-T7+CftvUTl37 zc+RX#J2Y!iU?UrYVCB)s#slco7*B`-E)bq%OY@UL;X5 z*0EBW>hdItZbT=fCSH&AFjoXiGQ{psDnRweF5&oLD#C>IVag$hbom+L9^SUN4bI=U zq(NNEr}G2e=gD^i#f(;9P}&oesq15(O|u z@5uq9;ppGt7@+5Bxs137=95+KKF4BDuqdGU)C8F(*)!FIgwf!W8+Zy}%I&f;8kSOs zOQxfM>y8@UiK=cp@K)Pp*%_`2;PIN4t3OJhEu>P{>x|4Z@1x<{Jo?6Dj^=$68Es7z zVGlkOlKTVj=^cH-7R52!4*=txhYV&|P}~*$TSgswxij&XOEN?lTaAAG=b?{X7+XbX zAk#Q@uxYa)3XVF`hgpU6uiM#BO*^jF-x#^N3WDIl(`G0W9s&lvh9@4Kk$4V_))p4* zO);6rFlw{e2^bWcA!|$?qn;}O6w3+@ zxp5D&;p+Kth3viy`VFJZ?QL@9PdPMy38C1dnr-3?$g7Q+i)rG4 zOq(P-NYQ?KXkAVsoh$NU&zp{-84$#w(LXY$&Sx{37B7iEi}oBP16zN)HcH!@`cwDo zuKo|=-Z@5;FxvKP+qP}nwr$(CZQJfXZQJhCwr$(pb7u1L@^0>ZlRL>IFR4GOl1e3& zLiXO@TEA6&iN=gXa{g8X6d}7^VuRUdri%IAh*X2K*!|m~3mRg^STu=RoRn_ErnCNB zTjF=7PTon|xsBV{W-VWj1VH<-NPPc^~J2LMq2cOs7T zxrJIuWG_Kp4KUa~Fl?!Z(?F~5RkYmw1*#BxsD%(i&;0pb46}dG776jV>_IB;Q?j5s z9PH|u#If)~@Y&~z8Op}d>v_W;z2Ic0c z$7^vkV@yHn@UuwH*6Fh#InzG(PxhIX(?nPi?0c~CwA(IMJy=isd-gZ|n5kE=*xifmeUjnr~g23?7n}B)zlQ~)5tg?aKNCal;>06eOd&% zu+#4x8ich|q{x|BEEmRLf~c_#DguHg_cZ27(WEqtg*w{zyzn$(Yt1l^tG`L!P0+w7 zH{Pw^mo*%4%R>qtB0kf!MtU{({%)8zGUS}8A^EJ6vs8P~vohIjG@zZe17Btt=)SaD zh#eC{Eds{4;b7qO2MD4{N+wKB+PFK8F9F$snTj6ISSGj~LQ1{Z$j$5-H#Vr_?a;hH zu;{T|hppo&^yH@6lt3$p8tkCS3ny;}DIPo*-EKVmaT*m$QrH&ZG%kV` zc2J&+YLC59LxSik8Fz7d*fhK0)@$f8b7%++al!74H^!Jg7K#IT=65pN4S=~50wf77 z17O_W8%y`-R`sMEB>pj1Mc7cj<4URewcE8r;>Kk+Xy>6#dyGu8hedKVE>TMPYWH{iMGr=r3 z4CA$yn|=$q>$%uIJS@Xv-Zfl@^su!(Y!=3Kv-{hL8=7TAhI;0ma8@g? zUv-x(%aOGM2yiRK@HmjjX~BVW2nsA#KRN|u3@bxdBTeoXnbLBB7wn|IMv`z*kgBM$fbC~k z0&uuDTeN?XhN)ClMlcw`MgMsWGB(c4B9B!ks@H%_ujje^O?svol)1vBx#)&u3pkrn zquW%I%RIMcnd+rPh>4^(EEj+Ty2%VaZvytox0j;}9)K^yTd8`Bf1` ziKYEQ#{$p#VIh?nl0J=!H^Sl@8RlL~hRZBG`%0-=T0&DAfN`f1mFMZ+OMa#vG#uR) zXMe$bCs5iD_S#|VDY3I{9-?6?IkhkQDm5trqwO&=#^iohxIa_j$cSM>m$=kMX}~K% z-8l1ltSVn|Vay6%fBsn~3B;vGQ^)i+CpwOGV~rfm>Fc3I3>1aQi!47)*1h#|UfMJv zFtW`0oMV0+g*afHGbrri=%WZo4AUXZlPm7EOog3Ev-vPbpdkj|A%?USOoPv{1{X;w zW6vuDEY&rGEU~w6TC!HcI3u8Ia7z?TnC4Qp``$NtFnCJny@Cuo_`-?K5I)=$8yD55Y7uwigH{I*ZsXl*XH)}i53lNl@ zAD$l_9?&V!gW#@V6~IRr5WZ#yHeRCWbvFAi)D@nY+Re?J&{&Inj)L&cDMo9Ha?7CE z>q51&`VGvE*t0wTQ;i@edW)eycuM%4nnUsq)P%gUuYR1rxChfdp;NmzJb2&Ybvo8l*GR18He1)<>G}OH z9{@oWnA~#zO_!B}YU+;8VNIU0u}I}`D}wOqml%{%h6aEP;YX-IR?Zu4cXgh3C_gD! z*&6Z0AXs{o3etf*@dQ{K2D+(Ii83pWrl;`dbt3nu)$SASwRoCsjxCsyo1GW|DO2-#NC?)QbVk$&N5Gd16`U6_wLX?oq-Ly(K#{R*7wy2YP9F{3aK=ds0W&jW5bIe#cvgrj^48;k+d5#S)Dyd)K zkiUEjD_D1 z;mw9MOCM}$?>86(f#-C@SE)Jr<+Fqp=%oPVCEswru@`gdY_jRPfJdCG1=^HnGqQ{+ ziKB9J3J$3`kEq;LSRL~zL*26bl%Z_oD6$Q-8X{AMA}ie=o%@00$v`CjM0f^h0tb$m zDkp_i%uIqj)r3Yw?y8gRDcHPiHwi}Kaw?ZaF31(#PJ|~f>?$cWt7$_$Zrm0rn$A-C zpA`uPN*OA(H_3|U3)vuz@HjGsvl&vLt*kCE2&nN9L#D;?uM1bE>?I+c&zmU`Q zW~?YXKsug_$>|ZbL+9q8FbB;*i}=owiunn5K&M}ALN2cjM-M1UebpevQwrIN68H(8 zNhiV%NT>ipFy4nMY5CnFdwUNj*-w>z0> z@w5D?yrV$ki;n-oN5Nk=N`*RKTy?c5gEy4>S&4cKd|*>{W$>|gY2Z9N7jv@Y0Bk2h-~jW zp0t>X&GmXEpRkp0ZXVTKP@ zc%;;PHe@FmFV?JFgQIl6M}>L)^DgnU`>@~0;f=q(W7;I-#Vg+8%?F_>2WF@OcD&s6 zg4;}1W+AenFg>#wyWyY5&RJzW{4Y&31VcF-M0v(z>3WEV)QxKHCOsVWQB z6q-TSR2iY_>}nlj*1X%!+M8%d1vfj~MaKYz94y8!6O$ZQ$mx97nq1RDDbcF8KQk5& zp+=u_)+V-r2WB!cJL;&dV?WqSwV;{Lf3pE++vaZ@-kQJa=HoTPzQ@_N*|#gG-Bxwl z9sEsES3NMt5H_Qn$Ojkj{p3Eoa{Hk3k>s?=DJ0GJysK#I0c0UvBzw)krsOsi$f1h| zIE19odFOX2T7)+_XL2sOu4Ljn$bxu|dQdrK2RcF39SdFP4siP5x_)9)YjX|dBQBav zt%`q6yZX>Ye6gI6&;@6*GnT~J&yA`Vi3uKXTKBp1LbtZaXBbasSy}9#B^$Q ziKoY7jSS#m$Y9-9KWpYpSoI=A-2C?J$Hw0MJpWVH_t9aY*Ub!PadeUr!floML#KhD zi6^-o?-~+w-spJ5nS%b5oNgw(2;#8kOoF@)RLv=0S99XLD9gDiE)2tmuJ-ob^@~Bz zi6#SKUNBXtln{wUyrp(KTUWyivE$OE9nHr1d2WL=HH4Z%fr$3$ea#ho&Y>0~yOgXu_%h1a_id6)j&`2Kx4 z)CYeZf!K)s_HsH@$Is#)u4q=-)%N={qdC7#m-TX)E-(8#)J6|~%YT0|aHC-00AiY7vBlrIHb@zjF zvivsz{_|SFW`~RCdcJEIf$|$*|%dX8r{@9h9xtsqe9Oc+2gLurhIaeh5ak?5}G#X@Q%UNXo7g|?O zB(W&SS67FBlX`|{`1sm!jrjx1jdUQTsj{Vu#cBEz0eR_{56U6VHxda_X@>zYK@ECP!; zE%Fnwp;3^4)|s+wE>h;SkCCIqqsuOYMVT&h=ak{I@4zU$@0KGsr%Lvrr-ZSA(!tAxM!-u3A~cQc==wvggkaaPii$%2)D#w3IEGeP z=`mC%DQLEk>?RNiTWQ*sk zfv^{kiQ;&B-ht(9#rU@rYR4@J!JNu?;$i3_GG;THnX?*;T*8*XAtn_G*2gXlz`-5y zFz^wmHta!Gqm&3gSA*9AH}VcA6L@zmGzG`|0Kg#L&=u%p>@2nJy%0-9yjB}pY>pG2 zNgw7hnj~9HE0hNp#xsQ_7C`E0uv{!6;KcBbwSl zeAa&t&Z{uA^g}yPg-mGZQUI6IPurgpDp{6ELaK62B5tj~t3ufg_Ky;DCu~`=f{sFB zH(IW_*Vv`Ol^F0E*U^#GJHQVDp^MB-peuiQ)y$>!!@YN^XG_hp^a*G($Zlp{F^QsW zdmdWp+3L}{J$hMW!poKg)vXO&a&AN@xms?8UfrfrEAAm=G;1HXM6(&^hFbeUh}A2I zqhADTU=HK%A-`L@54@ipiQ4wjLDF=abg51r4-3tSzV5`9_R3M-PKPPsDY2{I^!-~P z7T4>}02i#g{OE{tZDFkLOSI9MT%`xLrCWlc!NASS$Y`hf>jCccek^6WvlMM5PvKPmhgD2f=4Sv7tmmH;d?Se$~^<_Qt{`p zS4Ov7jOOzpL5irot+aG7f{xaE1nS;9#q=fk)5uK1={uh3Py!z=S!8m(miX|QJLZwA zbDIWza{&VOehM8&QXTpA00~dj$LCC+Bdg_K1&sWlYI~Qt8pAwQ!4D232}g5Ycz5AU z7a_NYJW4T*5a0q)y$p_XmZGk8WPZ(+?gxi_C1rI|>QEc=UTmmzhj)^z#{EYVHaZEv z5}2@~oBgp)zn%S2^_(KyLEG2GrpPA?n-&ZT$ z2O~jI<=&|*Lsx~rBfzZALA+&ua_Ta4U>#P08vUBPhYV8D&7k?e=d1P7C3At+<%_&0 zY*8u?kYeyB#tu_THxhw5lcp$6ZQ==${w*pZJU^9#5L{TYvlq1f6mWRM4zdiTR}F+G z>75K8DNr`?VwE-HlXvCi-zeQZ_urU3KWoY}SFOiKussmVnOf`N&knw7pISc*oEvUk z)1QvJumX7Rt5rwzUP>;Q7fZY|{rUzf!n^D9d=3>(nx~#<=kLLu=wc~x&XCP4Z}iih zkq&pq6Wkl`^MeTO-Z3`yxruY(3(|MHzA97wo)YikEuwc+TAKx-4YV;W8N1n%mc(r? zf1E?x5F2|AhSewk&Yo!hvJMBgRiHCQL*p((74I&^bk$Bf304fHOf<^F72XyNyuQ!3 z?Puda9XD-hyYBD>4;H~s=YS$RzRA4vQQ4fSCuf9M=Q-u>QxsE$?%G42^E_v=I^5U! zVX~cM89J%=n%`^g7|Yx3vwsK5$#k+F=S^y>4tSWdI6KO(ZxQEFRhZ0A zP8d*%x=7k`pd)o|_R`ooO>M`=+XOjGlox+)B=Dr;=bOPDnh0C0lRIEcwXKXp$U!8_ zctsa4D4|?uJFOApw~56U*>ipXHXCIEP{#HsA1lw&hAFP{aYLJw*=gQo_EECVE<@~TGXD& z-X$~zCV2{`B2gwSQ_@_b<(-|}R-+H8*82I66E>Vd5}@xA=^4MN_M6JdONzo%<`76? zb~uxsGC<=AC=kp9WuWH)&-E+3kJPT{%k5uKmpq;aa~e51;V1I+!u#G34Qs@@{LeI( zb;e6s{mOG-QVc9)8KB=31q(0*b%iOFeUdx*GWmW#OF!J?jlBg$H=z{iHYyj1*=#02 z8pqP^gU%x@R@BR^heB-W54)=bTPH!oOvz~=E(N3_M#z!wT6t!RG~(#lIU-%=;%wO2 z+@^-3u!&_N@(xoZsQ2=%0BtN`u%sem!M=R4=UdT)L-+NC;60{Jb4X zXTK>g)N6le{U%}_9*nE4o>i~y+1iEcqIPKWmw{G7a*CQDbfBuT>!e^Ifv^nbTi5Cg z%6qf4=Mfb&udbQ_H=@hq1?$p#Ks!vH{N}iVD`Wo{UiZ5g%?3Q>3C6w!o3YR*k+JJ` zvj-&Tc0P>XKjgp^4>V#y#U?phcjS02Dpai*9b}7?VDfM?e?{F2*QbZ6)ZX@oN>YMW ziW5|-7Br(Dgd{?3l`^OSc^-$zd=rUaLQWWr(O2s(Au)`yTv-As0w1tplMA67h=&ZM z1{`P-Tj05j>a@!d9@8$v3nV|RN+1b^y&3H$FxfKb%1@l5R-P5(d77NRAaT1vNtY9p z=JEtW12KO%$SKgK@zH<#nbAGCsG%vo~_wmy$FW^f4O=qU>Btvc2 zOJ0|1IgVnxex@XgzlC2g#FVnOtY5eBRN%^8Q;E~U=iVwmzD~f@GIS!bpir_9N z5`N^Cd$uJ7%ujrOJ%4UJd&BK!YLr#W<#M^SRb9CNApk&zvRE|4r7^| ze6R{DK(U1epG70`1tcsjAFClK7vn$)APjd~xop)iUI(lKzBsD$Et+c2=4w|i8}Kg) z+O#*X;N`J0!5FaL$=%%AuW;SB?fPH|u7v=uN&8L9?ft*oyxDKGaP&Tc`S8LIteY<1 zd%CwgcUpzXf4w?2e+zm6C@>Q8Ab@->$e!fGCq8`F^lSVPk_5nm^{y=ChVn+mF=+r` zTMBm5blYZ9(JPN9BpRB`3fQ8i?`I9P7_wHwPo=MF~^+&g+OQaM;lQMAs6mlWA?92 z_;bWxKA+a~Lp=~@_%-Lc3K2bhMqIUpfeUdAfp`II z7eX!iu=d4068vCSt(EsFpX#C$ey<_o31^Q7(XkBa;${(j_(BaMcBA`G#9`uo0rq_x^Un|g#_C4i)g5x3yOQ6_`vmx!5=NsELayZi?I6T-uf@9j z!hgO2A3C+3heUx%X_UU%0Cd3kA^4RA&wda&0_x%SQA2_&nl2H_2>4(Jq61h&;+@9| z@k=57Me_xDOCWy*cK3c}ZApF9G=*dD7!jF8f)8cKPuW7kTjB>uA>xU6Vp#O=Jofpf zj-MV+7)N|Z^`Um@Bk!4T|csf7bfdMAC}hj z%dH&f-Qhv5jO^h#Ko385oP9cgg3sVj#R>Yc44=+Ck@}y%t};vKJ*ws-m124S@hhbf z%qQ{rmqV#}1)ot23gQ3U0{-=gYSHghwaXv=QEC56@cV`JKAL-;Zk}djKk#)EuZ)NN z^ZfWV?u;{=$TK^SlypXOd(0Db?+-a^%CXwD zfoZVV3qfnc!D4~F=c6y&(+Ys(u)PcNvJ~yB|L4=P*Ps5_Yw)M;`?G=!{)s5R2M#^b z=aI`K+84$2@U#5IkE13QG?(jzBVHIWc&Z@jHdYCFi)j1ole_j1uNC<@_Ig3oq2mmg z!gTioP6D=<{w;6Z4vDiuv2)!$1y^+U(3t+E#d0UGtNE~yu|Iy%U}CfVYr}ls8FID4 zQ{(Er=f~%-ZJqwMxED6>lU<*5*?EFi{A9+nt5<=Cs(_~YQQ61@T@DD&7rey^vmqP z!lAe7)vC3l|5TXR3-5>8pSuy#tSKM*Mm~nmSHo8P!yBkw@GR*D8?ilWbkY;w7<|Va z0sQ%Y*`myTdF_y|Zz%1mU7(#U_Cjs{yxA*0K~Kg7F}PzKNeFchzJ({(Qe`7A`3$E; z{?z7}$2`T^2cH66ihtE9P4-Sv*sG0p2SuMGDTZ{Iq<%@OQA@;FB_dG+G zP|K(UgzIl@pXO6FcE@9mc!uo@LGQqPMWRMp9ePit(gTIF;NNXnP7)z_l)GVH6Z7}w z(BSyaRoj&>g87s49rI&?@H5a)>Tw;Un)@K-O8ykw3RJpapWG@f?JwVjHe;;R*El5g zL|a=7>ck(itPZeep^S_5>`wHOd%+zcza>qF)3@{mbHDrK!0lTe?e+_10j(Qt5g;^v z?89VQvQ`_Q_p4Ienn&#NiRh)U5}YpIWhUIKA0azA^m4>4O1KZA0`v+)RQ^+ASSw(D z;`bK{mj0D)K1b`Nw@^2p@y2)7r_IwOy59l$_GsgbWe;AIC(?yY(>LDq7Am2u^Kt!dKgs+`*Z2La%XtRlC02Ph&=)7@ zecrdl{7u?8jt!HMO>PiJb?ljWDwY>7%BLjl2&eFHknRIN;DmcJfXsvb=o8WLM*25A z-EcjUls}j+oMr0U>0Y`4YAE$j-3`hL0<%Jbi?~3C&ZG8|Rb!ZrydB9a5;Sr}#`V^pT@eC68cjLhb{WXY^OWmqrp9B^4zbB_|~D!iXe0 zId6(ga?8a2MB)VF#8A@oL~#;xayf~1@->ms`nzsxU9ElVwrjk1PsI&CGT^$B{q z?P+tK{9N+gWPV~H8Cgz_N7K^5a~jK3p5RtPwI9Qg>~9hCJB$!ZT63=mc)601GV zHZ1~$Y&wZ9&8t+qguCRkWUQ3$9QYhMR{b&Mgm$`(cqML)Bz#=4Q8G;t7_%bKr$c19 zA8D!IY^k4En1zAd(oo4>02r|%@a+h(3hW{oI~43_cdq|$0GO9Ddnq5%T>qbnKzIe< zLm;gBa@zMGAL-syIiw|l(TRqNz=z~yc{NAaH@^M+_FUeqo zrTCX6vTE*j_-FGM^QZU=`LP(&r_g`bnDejtmH6c@|M9w*t8A0&d6C5J--V;hpTOyW z+CPa$$Ln|)pT*~QDS@`maEyNJ-FJilukif%}AZ~t-_*iR8w4X1)n#iQa>ajDo-*eO&DPl6}KiQ*H1^K-uY6ReN( z^|ZJ9RuN2(yXAei9?UT{fDXUoe-{~?3Qmrj6w_V#6OPSC3Jd}X$s}o50%;&{%=c$bLH5v^o?2+0tpa6Y!myp*-@Fg3#i}TF| z{t~9;{oF=5i{**GiPX>jO{O|q$3A4%j#OJzzK8Y(;|IPv;MIVWJ6 zy*tq2K&=BiJ4DC<_u5Z<2mgjA*YA6W(G5dCfL{P;GZ)=)s#-tf=K;DCu)62U0gx|@ z+zo3#sC~!5GQ{ox+zox(pI-p_1E)X0S`UI#kFrsKx?zaSVTkDx0KGK_iKhXldk0z_ zkUAI3eM8lbk{9A_2wOdxF*fWqMVV@*1hJZdPeb4+2^am^-fjLnUNph5Xe(DJIfyy(s zJFepl)`*ajB()@weM0-l_5to4*%SRGA(13Eh6vLEg^%=h;PVdA2f{xv*a71Q#-DVI zaj9=e=ZE(loKw(`gg?>$VEq9-Nm4FJ`H1D5Tr=Y|5J`%%7-?C7c3F{^b&eoOHuzoy zTWZLHgLMG{OS0I4WulOgCG9AQ$EwJYB@eC`(uG5|gt#Je(gj$yXu^bLq8zPzzI09{ zOH6#hg)7QzPR5J1C(PFHwW*;xB-Z#)laf1L*1)tnN7f{H%|va0N)wekU)E509ke=2 zcf73O+y*Rr!mMH41}=N*q~ZOFNNvb!9jG;d*2wkBs5N7mncCWbZDstbI+C>s?ZiNO zO=)FvLxbD75w10+BO}{WgIs&2a}8=`TCGuft<(n9?1|Newkt+=rnY~}5A_pQd#u)M zH9>w{aqD`;xU~=M@%y zN5H>icm8%C{DE_OjA-Ao9XHOfdJCRCiK#tLhGc32wtZ|%q_ZGiM=CDSJ|oOh6J~Kf z|BU~9_6gl9X=L9I`R{=y0`{noCJ^=v(mI5h856YOIZY(#p=hbB2u2-JtC+69k?boeGf1mx4^q0P`$v<^HetWU(yFqQc z?~7fxJ-?^$d|y)o!v4Hp^Bu}F|8o;~{GYr3{-`+*4-buyr>SxH>P)R3GKPXbXWd&l zSJi)G6wiqlm6T~FBpW?N4(>t>?;Xq5GR`W-A&fmVEF>Hf1nU;9NW>sbRJE!uOzpLL z)TNqaGLxn+(Wu!pz*(2PO>L^Mqz+RrK{I($8gVGIX9{T4DW-r^hAGm8EZx#{EE9Xc zsc4+=H5vYZ-CI-Bv^2hE^p`{GNFk>xRFjbILv%3JmI}Qjd37vkw{(}5H}(R(+rq+S z*<{+lPtF9@2o6Mm5udPXa2Bd6~~t zRaQ$#NL5YGJS0u9Ne83TBzNy;27!=8TXt_u=;daJx!oQ2dwE)~^yb0(idj_rO9g0V z(L!JL$ZScQMNEu*RP&Ifjvs|pN%TBA%5n|%M%Iuw%@ICX&dYOcbYHB_8t9Sy($tRT zaiEc{sk*HktYmkf9X&20(DCU-F;#SvCbh5BC-R0(lT1s?`^UmaFyz(C*v@UXU8{fC z?j>fZR=Ua5HkN!yBh|2~K^Sw_M+wiRLK=nk8B<{fqH&W(Sy zQo46odIT<8@tSI=3vbm}MzgKD2j8P`j|&Jk?8ARGGxK6*YS%v_D<)JNg)HJDFr`uOWoQBmUyhp+%_S#w{8M{N9S&CQu{u+wc)`R%ViWwZ^;e6&=9KsIi=blW|gBXro~*)q_7e{`*4GR;vB>65pzNc#QqC?n9 z>UT{bKgzS1Y_%Sw%7`T}QtxS46wpYo67pWE@=czar=vl>TwEQ6R;2a;>$03;cB7!A zVjQTlc>5COP)&+XwtKB2)kQu!Y#t=3rB-wr)FS!DSS>(|$yA57?9DY}top{6y zr%f}Wy@Lm$i`d-4{Os&La^#5ms8x|?HR9Cho(6eV=N?AgyYHwe`c&`UM~KIHq)CRy zJfd8g2b9;&a%_C{?FVXCKZ$;dm@qmZ6N9lPThbGalKn7qLLjIOHOu~tc;I*>^aRJV zkrTgAfNwV^v=nncDTeaICZr?=%9#;w782vGtQI^O(wKlrNPkBh&%4oI_w3xY(BO>N zbd!mWMV=+Wv0nUO5tVQ&kid4zAv1quzOmwfHlD9@+J~tt{_n2Y&&XCe`Q~5#>`w~H zc&6V)pQW$lcgjcj6X?HnCOlR zRDhIR=qAyH?>=XAj}}c+ zImT#ihwMOM&=EI?!_7{H+#*HC|z%x2Va1#e;(pU<3kQ|ENPG-+MBSd%;ut;;$~}Z zmp@LwpqZR^(HTqH$B^=q34+UoJCsfhEV`g+cvARGEP>yl6XxGp=MXUnF2pk8VDq-y z#+B7;Rt;~S*N80MD0(|ef<|n_l1Z8g1{E2gk(mmDN~{7&HAzPx5>CT1F)(u(s96f@ z^2n3slV9evU%M#*r2%JK41+PU@OKo1E8a04d_E!5sdFCsgkJ5ybQZ;3M3QQEwG zl!ox064y*d&LA_45_0k7$odHC=M@lN&VTCUTAl=2*p1~{+F;lVYPfVs^OUHp8fa&C z(QtIuPdCe1P7I7G?M-L|Ff5ocRD_mBYyV|egk_=>L$qYtp@5QORSU*rvv?Ee^#e1= zNCk5M?4CmC-!<;;e}=t2bNl)ie>sQbQc={E8`9hKb58=l?LdhU?dx`9-#%R4_dbw5 z?a6+FH3Hu*Q{S8UyzPF<6rEZgu-NIdS@Z+Y4*+@*PT~SGD!?ck za?uE7;)!VLhXj-8GOxcPk_dAC9mwq3=URiQOS-Jgbz7jlGM(nx#pTNZ`NVC+7m)|qL0=3n?r{?`X)cb&qOF=ptQUO*Q& zpl^?sAMbXbcmjnfoMW8K3CaF1=@V0D=ugONyNeHc!?X?gC-rB9FS%@@nnb>3um4#A@w*8RC8=ylYIQ$Ib25+Q4$18tmsRQOJg^73PJpxhfJH@unUvjmuHPB{W?!Md z^)GfW!!Fyd-|lMfVudX81rI7~7A&j5SY}-i_FbA6KhGq8ZvQJD2SoVZZ3QQAZ!Aex zh6EI*Xyg5fzKB_prU{@W8Qy{{9r_NKz&mQHiW%VX; z#r(Pk;-rul==6nBnscdhzjMfQ*>mc1bJ_Y6u4&niaqG38@!Q*ueKAmhXs|RgVJ5wuh;4H?G_su{fh6 z-q;@{SuG1l%Yel@%#L^;vC{z-FHoDbEY{nkz9bnY-Nm3E@C8J+RMvTlk0s4~C_X@L z1|+!t&?{375xe0tegS4fD%Zj7E6fM?H9@-6EKO*sjv%QcsF=_(1MX}h&>@nw0k{69 zBf=NHi4gJ<)RNq-qdz>l;QSW&33%q(tfC7JyMMmJ$G?wgckw=OQ9kudA3w4ubd`8U zk4rIn=#~^1c%lw(2V?F5&Jd+XJi6h&S;3sM0gJn#m{&s`7~k=TPoS2R5GBLUSuoQU zBDplNVGFP^HDXWu0N}rV!A*Yr!Jc#h+-86AN~i%@`o!UV0b8Eo0t&$i&b$K>&Vdm& ziUcqwQGdD$4X*gXPxo+gf}I`UW(GJp{>QI zMG0S0Q?Ot{95FZK@MR0uj(lL^#3n3se(V&>kA_#LOXt1FdGlhaLRkAf3ZK|1sVIqP z$w6=cNV!SttqSMwWGv0~AwTn8zJ2o$U=Fh%dSwWKmgL8HTi8Pib-vb-9HIW^6>G4 zmfgvu<>;*ks3XM`&2hb4a&pJy+u#`wj=;qQlmy^838?>-zi`uOI@QtI<)==Q#v?gJ z7`(f1+U@wuT*M&E4{<7oh|p0&gpmBqaj`|BN(p}UFpQ|kL2l?;Cdr}j7=C4k=z1T# z*?!>wrY7gc8e=5sP+`yN-tp{Pm&9T!_GL7#=p{y58z9JaEC zib?`LHa2q2B5K^T+UxG{HRyM9|0DT(|I=MiU!f*N@>%?6m7D{rd+Y zVVO6ODNkqUG8B56EOshKKh=*6?aMAb%ijd=Xn0>QXs>8Ewls871)|_;YNHsY;5-XV z+0_e|Dt`-$q~QuUUXeenXD;al;Te$bNHV#jMAA|ae)cA-rHLd*Bs)ojcF6X>&7xg8N_Q82 zbIC3S!2LN#)el~L2}h)m2>{trz*8B-U7QDNv?$}ar+AD-3?=72AUY`q47-=+Y`b;q z=EcUu;+bT~SewP_VC5mRk!6$~3h=x-j+9C`HPG$Tf(pgRJVTP~hm1^hH}3ARAeh7E z>o0~ImK`$}=f4)?3`OL*&3F{i?}9puM;FCI$6YfO#AUQFtScqBq%SbrhAI={tz5ex1ejJahi~9CXAIx~a?mo~G;j zKHoBAHy=>x3wnnJW8!VVMq<#nw@dU+ju;|_f|bE0BOPWEm(aVYXV9_Ha5<*TAUXT3 zi5hNLAWx7=3TiSw24@Aa97^~pSjwHyQ3XD`FRK7DA|%3yV#HFwG)%#~^?6%SXT#IKPx2j!`(eksnw`>e8X%4B>uPj7 zP#R0&ZuNb-c{DjF>v8#_S3SZ!-SD)=e>Z)0JzVLV?X&C!d1gec!GoWuw`V6Q#Dl3o zXo`u~s7=MHMYZ*M_-KE=SJL@Z-Sgm&*BH3$BV1UseiG+|3K_RXb zcPIVFiARk5n}`%%IdOuJ3&{(tJQjNlIp4@PokS6yo_!<)!5-!w;vbTg zm5{_H=ol|E!jJL{ak}UE>$2TgJlMdf*qt!6IHKHt$R769Y zeJ*>+|MT|&J^Pl_;jt+{B=B?vnhivBL~Kg{7;_+*3|oRl)<}^8F4E#?nXp0%d6s8P%AAC}Obj7gD;P`? zc(O3vZ-YC2?2aK*cPk)r0RJ1~Ry-WkcQFP_hxjsx!O`vFnKTc4h#?VximFNEJ!NP;Tflue<(%?@2pQTg^jMi74_YiuhPh*4u^i zRUB*^opnxzhx`^sw)IdY*$uDp2Yphl$gN};P*OYgLW;%Uwm{1JmjC3Of64rOaV3hn zQAWC%yf(L3a#kjLSeaPaXo_H^=AcWiDHAB@NO^eK*vOc6kj%WGAX!pSIap3nyq>xq zLY8&h%1CK;^ZCgfK@BG(58Vs`zP_;lmrB||^Qg$*GMz=O#cVRmhRA@(j1P+oxL{E> zBQ)P8ACA5nbtbo8m+`*sxhC5`3y0*s@cfHRmeW@r zT;(+$8`Y{Jo310dr@MDlv(Km*MPtTjF~sx7x~I}4vf_UUPZX>ODnBYqr2G-J%l(Ok zR;#ru^)c@qhLu0ciJFz_QN)Uaiy3z_4k%)yn zz-UhR#q#m(2@GIHU>TNJ{Da=SK;7+*mxd4fM{@h@?kXW+Nxjl4dByq$4uHU^Fd|@R z4&T%&p_PMx^ywDab9 zwmVkGw%xI9+qU_}wr$%y`Od}O`y2l~&fZt2##nVztLkE{XVj=wYtH%WC^0Vn!$(^z z4PZ_vOq4i4Q53QAa7vrSW@Cib%%8jQ4OW{;OeszPIwZ~(#9`-gn(c}!tf6QBVcW;S zY&2OBpHO;tvz%5JDaK03WJ*TjNsKQ66{TW!F?>|T-E>pqa^CJ4p`g6j*KI+-$hAfZ zw0;{qTCf-fOlVAKVi%Dc%TyWXA3{&)M9Sp@?^;Q1`Ji~Rp+fK6+P8Lo>CtyUJJNOp z9#SDh(FC9$1n~LTZFdA}I8aLZ-?j`hT~oug%nH+5x-u@xtB;22W*mnlA}4}-lY*$m znTnA5mRafWamKo6{0cUw%W2!{Ldhx8dKZ-sh{9??x<01st+4dlJ789FG;o|3RJs>w zkmS$SL7f$Df1v(_AG#ba@X_{}7{Y*Vk%ye6EJIdBsc21eLTE@>6S=(2gv{EdPH;jW zos(cXCnTMln z@^%+9V1S86I3v8Xf~CF!bvIIMPk3IR>S2gB?{u???i?Z)rYjficoJSKVhyM%O1ELq zd0wP<=B$Im+-Uz13^Ad&df7Axm$|o;p(Ao-HH^o6a^Q0>mWRT!8*0jCP7g3ttHt?c zi;(W`q2?D69SfWZw^8gk_!N z==u{LJ~@|%yBTpdZr5lU%L$LG$br0g1uE0~CW2U&-LqLOh%J=@77?YyNK!3P94_)Wa{R-H znq+?hGB-Dj;!iBraoobW6fp?$(SsIpS8;UyAK2oN<4Sxx!5Q`jO;|3MHV;hS8`oy1 z&9%FS8BAq}`jNHw;xwUNbS9q;VW&w(vfK(Tucml;RR+gwW1vq^-d-ULI}^pi>%;;p z|3ckkaa+WSD3-+k)JwD~_X|@miFNSqqVqCYZBBNK9agKw#;tzYz3zu4yL7xaH7IMW zx!FlQhA7*hO*CKXF1f528Jb<+KbF0Qwqju=_ea~ys&^VZRT4em-QC^I1)+ThAJ4Jw zH3hNyOg#e7rJ1omQ{Pv z-l$sibs<#G%eTY4(6nl+{iq+6Z3q7M7wL!mAy24GW2*dWc{Q{>7@EdTSB0K+FIc=v zc98+>c!;i;O=mLvB`pC4Uv#$K2?*iLB^*aS8ruqa8+p6S-|^e7_k@{Z2(xYxIs9@1 zoFAsXLt&5Me=?d?VR^FdLN$wahsh`DuE7O-BEuZq2Npy94`py!s@1PoDt0rbDnaFt zJhK$-CXb+fO+p@@zVGY)b#2*u)Dq^vmu;)XFaGr^@VbPck?cL)CI~qb49G*kGE7G7 z);<(ucl?K!)&s*vW8{jdN7wMv6PqI!uQy+DgaONfuK#5&>;hhZ$UurZYD%C&utD>S z-+mNMoD7J2Zid#aT{_)TYekhb>Y1MlzU3BEssEDa^ef7Az@9D2OcaYpf8KKcNYu91 z-jfXmYqfR?-U>uQi=#T?kBSpn;HEEjoEO{)ovAuL@(l%z@DWx{+b}_OR-- z-)u8<6#V(k&r@_pjHNcQ%wAd*QxpT?0sIoS)H zepkaQx63+_!V7FsnuDo0!A4u5&3?4WJrfV%sfBBM;>6tHZ142BC6&!;D1WR4$c>e4 zy*VvX99pASjy}_!+m*2GvsCWB4R{8iWKS$NYb`YO=@BMX_Nj!q3=0OcIeozEHL3{A z5$#If3_3F^s*n7=at7y-8vH~nGg=K`S!YLUZ(R_#h8vzCGY8u|<0Rf{nNrJ^$;=n9 zJw{El#@$VKRtviDp0M9)f>2o|@zg};s}Ve2q=fArh=S0tDDj?RC-9w(q z6<#PI%7AjfHl4zs<%2WO%ek^c!l7eTZGa9QUkAg2~1Rdz7?H z^_RnEKgvI(zTuT=n1twng-xO6+4!KgBZOK-3q`YVDfwhTp z;ML7P)m=}<5nfa&u$HHttFr%Og^ffl$1bBZYUWs@p3GXwc5w@83{#3hGqF-`yimDY zvzf>w_U!hW#-H{|qCG!_HnrWS;0{+7pC@7&d*TWXY4)*kP=6SB6mVPOr;q*=%{3d! z!JA|~PDnz_afZ8H^K}^LUPMiE0 z^_MqH%fGW-X5umIGqL1U{=?v}D(0!sm$?YoC!=!3hvnGIRG=q+LwT{75$mY>x6o+S zI|xq8WNvkH3poewKvD6j#XWc}j2jlyklZ&#O zyGg}Odo44hq;4zE!&9;3O--ZqcoVev%{*(DP3=i*ION=GypL>?{R_11l^j3U@MP@s zH!e)Ar{c)la2Hipg8ryLIX7`?JGU0rPpn?rdKhYkFBmnt+5TJGt7$co3vbjO?6O{2 zA>p=7f=}+8v9535kWJQXYGNN%+21m=h{dC#7HdC0v1}gGhL?kdZ#F2ekBvTbEk`@* zxlutK+&Vm|Yxcl(E@&c}Jvp6>4V26nyP%_{o7$_>maOPw5}X>Ra=o}JTf zWEctK;D%#0{bg3$xuJb1b6{d$G!dG=&pf?xrEPX5s^S7)GbxV+ck|fRr9q?p1=Z8B zy>o0s@8b7NOaYR}J;!>`pWBpG)s(zsO_6iK2RaFTu$&^#BYJM* zThRh>@rXn52y_W{&Bp*!9)(y0uo_qv1x5ih(fM1IulJP-0%8fE}3g-AOYs z_8N!w)^j!lcNr87qu+Fwh?Bm5MxePR*Wj_Ij zUDWi=P0kuP)4G+`_szZe4*PBwzd+kQ%6nK#2Ydh4j$XpIPt5GsWOmwPH7?V6CPz22 zv2nFT&d6x}Dm1z=PM)qDMl<=jaBAvs4Y5PwS2cE`ajK%FBaYg&$6h^CT-EVng_uSG- zSXcY9#)Wd^s^Y+btDykzPGawOAD{wh0NHHy5UYk!H$^$I?PO^MCKe2Ao+gi}&#fZM zF5~ZJMyP#L247Q+Yl0S!yQQ;^o=#RTLp3(eooF;2O}~kqK&_S*OOc_pgsFV^&>SNj zdvkd?b@7CaYkIwvt@QE%OmbuR8K@9qprCAhCLCt&9Ai2shAiho2Gf9b9wYm7~bX`0m^Yjvv%S0D)?HXs!U9PcOMu#vYT>& z4yAh*lU0~!LW=tqiElK%{dg*HA#3M(iMu|cJy$g!vivi8ARL*wAtdQMaPzZF+R-bkIyN~HYcS8w=v#@ z(>N|fhCDK3#LWc?P@xYHk~DMAq(@g8`=YR)S=v=7^VjD6__?X=(qtSsr!0-fSF^qF zlSL8E_O$|gXd>@{J*tEzpn^u=?^Q;Y=ErQ*PmqzxMq4klrTV#d8P5uABC@D=vu6_9 zMOv}BG7xp7Hf2FOmvY0B{%-F>W$meM4WYTvba)^K4SU!xIrhAkUy=l&v)l?gNJgA9 zq`BJ8-TO-)9MZc(aj;%>{oF75rxy;o_qX_(T2^?O8dVrUW&A}i1t7DWme82tb^im_ESCp4TYBPZk-xV~Rh z`YR$L>SI+96=#w(A#~w}w|qxg5)^G+m)=)To!wjPOGochydOMM4wJktWT4T+}DjLGe zr~J_*+Of5<(oiN=pNtD^fgXd^mdTvFEqcrQaf=TjpK)>G^eBv{p#ZY&1^HVS%JKX< z)WLfE6CvrCsT-m(jI5^%fp(5k7t@o`dROM@*9znS5=}WM{4&(pNH_jh8ckB8Ob6#p zt|geoiC?s|q#I7!Z+KV*j%j}|+k{i}XYi|#3b;`PwH>z7LH87>J3Ul-C>meQ9R+DO zczr!a;U3Y1hiL#>&5yC59W|Dk^FDa;&Hh#XkKD?PFULM(%z)P4Z&~3tRyD}hy|(Cs zQu2p=)-5Pk-XNmqv;d$cz4?S{8Sl%@P zW89V=tEa&&CQOeiHWqL!M4J#}qG!8{+adlMg3m_=Eex@yu!NHfBFR_*0hOc{O3Mcz z@WW=+{h^T3j5}m8WKX}V&D7+G7Bvy&U>P)~084sJ=?Ng`-Pte3ZRGj4Lzv`>e(+B$ z82lqsV;R>bG#Y%+0BmlTiKH`pimZry3vPr(>OssLE5 zz98GX{($*3_Qj}Rz_5s}S)biSOF>ljUu3^p*|r*;G9j|A0gaNCP!okusug}C&#C9l zo8ZAKUYFbF#3A;XhCNk0UB`~+PJw8b!Q6zr`5c-)b=@)_-ka|2q@hQGVDcGQ9Z_vQ zNSALp?GGK_GrgZ)yGu3DtagBlTay+LEn5Wlv(9V8cX*XvFI(<)1Ox+E&28vqu=eez z>!06%Iekp8H#S!=O-x^l9T`_Nc;H=0Ve_^?3#`*S?zxE6C(T}%4vTKGmv=!UJZSs$tNZ) zrO1*EV^d!h+dNu~e5Bso#;U1*1RF)&Yd*wCbKK zd4X^bPK~S!cV$%6qhp7Yl$qL!T7T4HvXiL~4NZ(DN5$o&WF(yX2L`31BT|fEo73Lm z+%ub1@>M9&?6IbhLMR*1SYfJ$MU!b}RTPn>uB>EIrX2+Y^QC$U^1{bj0z^wwZ0#hF zq?)u96%9!TO5=p-4F!!YBjim{w8UU6`zXvx%7D*s5KZpAtYiaY1uZm+Z8wAIH4GI* zsA)-PKj~&EP}{;(XmF@3zkQNHjcJ~mT}mi8U_fkI(MC)MndS#T{K<-NnC%=aa}cMz z+nlwwr?8$q=6&xY9NWvb0UX^m3|vVQ`M+59A}zF)@!BzRR+vEZh}$*? zSZ6c*<2gYZSxhzzC;vQ%YGSe~>*XJHqm4;dIZX&!0?c(^=|R7Mp1lKNY;4Um`Ih$Z zD=;uAo93rl`XHkHWK&wO!FzaWU8P9mGqMZv%18Fg?pmKsJSsm>z|H+1Pq|9NiqppU zw;&>Evoz?$^g!^E<-bL6J&@vSb;=7Dfd!#^KxT+By0-b#6Amrk7t@5{zTCD&w&cc{ z*|5(QvU&ABEq&gy>P?lSieiCVGo+i6(G<}s5 zD)WZGVBHz{x#Rw}!(2TD+*3+Rtt5f9nh9&XI^`uJje^{Xa!rfYIOhXchvAI0j%Cbs z*V`Z~L#2fpaW>^|{_Vn^o2`<}#!s=9_rZ?W9kUeGX4RfZZOH>uDwzUy(9T@i2_R15 zpUpZ|a5eIS(E{+3E~A8h2}Nnr#M4ZpwJaZo*uiE@No0~{_x|Wiv_c=dI+_#>ifa|6 zx@_}ma;oUyd3ZPcyT6(&ZS9)Q_4+6~w6N2erwSVnX6|v*vVgN_EZU(u0-(@T!PeqJ zk!#(er$nTB&C?kZa-9BO_1fl^0vBc=Qm7J6CG`4*=nZh#@@3udHd<$=+7B}gb8V0A zBgqeR6tzYP-!8NsOGphf0k-dVK?2ck{;p#Q8 zA?BL^8f7z6E23q!HK^p5!FA%rB-r8PD8~)YKP#ID3!{LLH~iR3gEJ2l(ejH+^}SLq zIJ^)wHl0%8#9cXrMHRN!D)ym=~*I^$f#pWYqc}z9&oO{XH21T<0^NhW97w4?}dr5!#UpmWKi9$_gd-wGpy%5}o5CJ-SI5n(f7_24?N1Hw@|RJ4*- zIJHMEnm4K-aG(X_k%ktQCL@V0dow;z6x;r+W}j6}vA+fiVyl%QLd;Bfr?ru|vb8aP zeSx?YWpVvwU0KaDk|l&y%@ht@!yjr2AK;SHLAAljpyk)sON}WjUK>8@P+przU7P3% z@Q~-Abj=S|rsun-FawxYgIV-RYMFoXxMO*HZG{dE4q{RpNQ)D<+i>>rlqN?6@ zk}R!Ga93z+RWWnBHpih3Y4k(wKU_K- zI9v?N*IEkEP;E#)+pfZtXxRNgYrp>7=Bq*&qOu=zAuT}HJH3tFuE|rdo(%b0A7x(% zsK=5Nt%wcL5Be3<7duTM3?jrQgfB$rKO6&$nTQ#P8DR(~@+Zn9iX=)T3M5L^BNIXv z`XvM^#N+QzWKBW>f;5H*M4VvoCkoT!^3NoSBl6S3_KzgWAc_$9Tf-E<6u z0}uchL!$V{62%bx>&@CLH6}xIm&H6Ra#f*R&l%pb`KI^RuTWTaN%3 z5AeVe#qyr23EqJY+5og;ied&~X#t|6!4HV>4W99U`G9B!p7Co$pbZwj;qu7!58wyj ziE(|*76Aw!)Q)wj{|pDr1h_D)PhMLDT>zRH*GFw(ffE3B#&`36t$)jd*HS^10CuMJ zo|-^CW*{Pv9+QpH(y%2O!%Vmm&HB zd4M{)M4_AO8F~vbia9EgFs1Mrb&EB+CC?}F0)AkS5G~Iq{PN=feAF)CNnumS4dVbW zp*!y#;=n4QS$Tg=fbd3+H!@B_VsV0rKGTf$M<1St7Su~viwodgeg=bZIOdyG*V`OEvZb$6)I z3yN;hl_-0h(MpQuob?EMl+kMWrrdXAqw+<)PKEYWcd$|P3q|SxMC}k(LyMnRFnpNf zk+Qg`IDQ6u;T646e`PT&;Wn{7U9R_fZ!Ku{y~dK!WgFBgMDhmM5y2u|VlfjKP{7^* z02)2aXKcplXH?~s4q2HqKJ+>SK?gW7pz)5)$QKj@SYD{ zyj^FWM%dC@2RLCzHskEi*#2SQUL88~cR62$S$DauulGZ??yC?VzC<+x3<$ zMO<9&lO^{0o4Cnk_PODf_9B1gER8)Gk_Y+68W z1rJ*UuM0iJ#6NJCxFSMWn0%3bV!;P=ymo#14tULkBh9cBfSiP1Mh^ybnNC6Ff6RP% zeIR~(0fXOd5Vn18{Lu|nF3$32qX`-sP{XsB*dGGU4(5Zc5VpntFQ7Pnz& z-|qdv(1KgrCUS+5MdXhYT^$i!{>cvHbA^Nlu3ZyJBl;)`Vvjg|y+T82h0(R;Dwjh68usa>%xLwAd4^8up!uC^JM!Sb(3%E_?2WYWj(1ZM+-Kfr_Jh+kQyP5bd>tSB1Aw)A&%ell8Vgv;2>CL|jMi&Njxb zVVYWXM?GX;6R-L*HWafxirq6Uk5WsMbXp23Rd-76HTQ6?$vOfbKVjd|Hho=ocwGsi zfY1$JL)XynaNmyH9@T4BPq5-b?4cU?ayvmPyVJpyCMiiS$VPmL*6>enFE!&~l|GAVaNkpzUFiXx7={kB~zY zU^Qc>zK=LRqz#3-fBU8WowgvUFoi( ztpas!bgo><-M0=DlqD)~5UikXX3Bd(TpZNMd%6q0{eyCZ$eA=h( zywSJv7toDHA^AcOxXWeiDR*c`_V;Cq^D@R}{3W2|pmzA@80QmIh+=*}mJGnL}n2 z(CAHWn0Oy;%CN1w?=Es)GVds-XIOA&El+JUevI!)?I&@%csCy1W_qO_Eq051=?^j9 zq)HRZ{ouCzON{+E1iZG8TZV>ig1Xu>%z;?v6mIP9j>TiFc zsvJ$s7a%OOUGwy*seBR<2L!-CFh|%(N-FB-dstSSCCf&!;hwJD zKR%YNz7009^C)VzS?uKDB#{U&>TH<;5E_qLO8BENrc!k3@7g`Ch}WwI7ISPYYj?xM zxRZD}VkW5n*!yLLI7Ewh6y)=I?(ng>Fpf)=&YyBl<_t)Ib(u$M9q#QNU8UO$CsKmz z^teQ+igY4W%iG&mYE{j6m^rY{lW|H&a3JU!xNB%=D9T3lCKsgRNk|k4g$5(Tot(f2 z6NPHer=|I{^Ulj)PEotz*c`c~>!xHgqJeovD;`<4dkK{>U6+W1z9}lHqDav_5!H5Y zPm=q%_I`Y}C|KKV+1_*7Ppm|f5=8v=ILhmE`Wwi^c2>-g`AL}tErg~q&as-oZJyBGza}RhKBq{>ItJ3VPiT?v-?{8hIR8BE~(e=)~U+Y+7?!J#|yXt zS;mBRv;K=sbqVyCU8KH?3P=8P?|U19iBqo{A(+D2YB3Me{LTnO_@$cKD`*D$3{X!| z&SfLTAPP}CJP4}D7w=q<48=zk(-NjTo;p=^ zR%X(?)i+t}eT)~MgYBjI-*Xq^vdV-bi@FB2N4GZB_BPGK=#$>--FBHjaaXDEnrc@r z>(>1B2rxjsV|pmX=6hr1;s|TxaMv&PH1(sgNH^t3o=1SUf8Iji=C_63i!50_2i2l% z++Uw@W=zL`rqUTKvTg*zpHQ^Ym%KZ%kNfgjvKY-O1N%DWfRH_2DV5&r@|GL3ys=r4Tit8v!Z~r_z!PVcgOoB+VMcpmK}%7wHFM-gRSV{ z?-xPt2TjjIKG1s{<9vHx(^0~v&EI0YbyaI??+8P5@&)f5N?l2#e*@kHatbn7A(hVO z;xen;<%z`GL^?Y=T{#~89gnm25kWP4w@j>hTXT{(ZApb^LStEBFnQK#Ce-`3X&kCZ z0Cau-CLxEg(kfx@k|`$SSYeVvqcJHohcN$B&JbJpl$aCk)#kW?YVTxvw8c(=(Z-%A zKNL?2UH34ZuQi=Oibt3?TbAga-^{NHtsQ~?p++Vyt8WL!h-qWX?gI0<)an;$qAF!T zURsj+0X0>A-Qs1tI|D;5Pv_2!TYa`h+xzBY|6H@-lpLcfI+@b}Tu|{8!{EdjJymNR z9phLQ%6DXdD;o)u`{(P+Ug5skT*My>XKOQ}#+B`UjQ2SvwB^67bCV$xe>aEJZJXy% z?4l=s-*@z8duyI+L%)erp#w;n#e}^#6ZWFJeVOCtd$TOQba>|l`u7bYt6~ZG7M_cx ztgF?%u3vZSXs0TzS5o3SX`6HM=lSw0h~+5g=m3qu;78gX*QeA7HmNu{1oc5f6F3xU z8@gzfY~b!v9(!8%zAiU#Jc!x*w3bO8M2L7j(LY5`e{8OvkPy~T<*Yi(>S9SldF75w z8w-C08Csf~UC3c{&KGeIIsW}6Lq@vLb2w;$Dk$LQB?(L-4Mo$0r;Db6<>lS9ikL`` z-H1m~#NoBD`)ts>(64AUyzc2qBF1rGrLqUEln(@jZJ zDILf(&Yb%XwitVqQYi&&?BCIlX8vJAcp(C91HHLr)ER-cs(g)cOTB@K+#uGkg2}8} z)4(KZR@K$pHJD;7|E!tUSBkqu0=4$T=ryWa)eBVSGiJZ)Q; zD}_nT`-L3|;bK_m2j%RA7dN+5&+8K@+bwJi8CE`J%dNgz9NXg)iL8l>>DuIny2|L#>#Tbqen zGhj=*TQnS;mBEF__dh^Yx0<`Ug7;O6<8Vk4E*8rV1P` zSA?(&{Q^x;kTN&8GXPZ|##k9GTGG+Pz}YqkftiIh=2dV&f{AvJ>M>!%VA7@U)KQEyN~CCnRChV$sb*89W@AzRa4;IttAtO!YS#R!MUuAZB$M z;NW~DKQXfu1<9t&-UNU~`bE$(r#Q&Ci27{7;NW9|l|?c2NmLsYsl@JQ`zo9!y9b{p z13fTB`%lN0sl=@fNURqeg_pvOYk(({@7`k3^`4^sfmk3FqGDER545!x0N2ixj}-|a`8 zy;7C(l!?E)(-aUr&%?TYA*4|$2i6G+xT>@2Ld?47LzUpVQ`l~gatrH1*659x}U8!09n_@u#W@8-fZeL4QcpNNf`%m6>DLKK0{>+R5wprXl86 zjxYx@#9#LOAsw{L!Xs{(S~R4e;{0gqOVizqQQ6eBKCorM=B^`K>a5eX9ImN2n=}`PJv1!O>aOLn0XpEQ5Ns+Y`E1lLZ8^E@`h9k^ zUrDId_?3pG|!sOn^LpjFK`|c zE=8mdPFlFpmw3xUaM4c@Ux5ZvyD=BThBp`8qh)!iT1`@FW~emPjZQjbo+L8MJXrm? zVqdE_kQo{Cu16)=YC)Nz5VL!Swhcal#;_h-N;P|C;>v`@S4ahlLX)2oX%S4m-0mP1 z7oF|rCYF&)K$eihhnW)yg|40v#A6rJ|2hv0z?*=V@MveLtodq5h263Q1>@bqTG@LJ zpR}@+LO6KIH(FX(nyYWOzv((1B>gO{RCY*87AK(7rUodQNq$74%|r)PoXBK1M^>Q0RZ;>fT3?l(v2 zwTq*80>kb)xhHm4HD$TcM6&on%9uf#z5$jP&g_AQop}}U;vYV&3Kc@L)Oq!f+f$&k zo4xUd-uB$*U@9ki(Zh3IN@%GY`6s?8SR@)#Qx)8uEt&FZSa=e@MvQgfccn?X^BVXA zKc?B-0IV^ME1c@HuNb$Z-^pqS32QIRd&#OxTt^N#lcfdm#_AzoQ#kI#8hWo5`nb0sd~^1xI(K!T zRT~zmdZ_oMY@QD<`P-E6jMv7U|BL+#bwxzl2nSst(RKniW)P5x5M1)yL$OJw1U~xaL!=Lwew6T|?3C$-2x_3xO`n6W>!!zsH8hyH!^~ ztC7TOSZp~QTc?NE+-`)gcAU>cuKv0`&gDcWzE_Ez$7lNS(1<{^%(7f35IX+Eh(zc|mAa{Gc@gMkc&Yl$)gTn<{)>@<&XrdQ0Zt5fwmQQ=TmqDkquxyUrNqiLY!mF{_ z?U4~q=zZoHZargpK|^^#L3xsDkzyW7$TzdO3tiFGu835u`&xn&2#1bT_8a4Ro+1%u z$@4rF>Q|8jQ?ITJN4hB`zpRJ3q1lHPC*;@LzcI3fE!GdS7WFS*4KuJANxVMGZ~yM| z1CO+S=Sn|jxL(7dWeXfhTEA>B?Knt=`#E?kX?B+J{HpVGdT8psEmRj6;~HyL9hgj4 zMOm}cbjOxD1O(iG=|)@;S}VFOYwv6dzJ?Bd;LYHE zBb$P^_K63@3YZ5aK4Edo(Nv^g|D^)>k^aIkD6IJqmBDEcZQtb(wx)iP{{73GX8ekx zkzGBBV|0rHHqzrL7Q4yet&&NwOdq%^&BcUMke%68(tfv$ZJ{6`ApSaG)ckp<`Xuwi z#r%DKcab-}e5CW@>A`Rq)%+#f3*cpyOn>1075dh0_OMn8mu45uDs?BB_U`?68I@OZ z(7F8H9c}XbsvUe`94nthkR|2UAm{^n`1*BY*UHU-$Q$tn>1Lr)eAkaG9>~dO^~NHy zAuMC#vA8(UW6`odb!Zg{=q#HaT{Cg1QdM@1KAuz*7AF_gR$T|RQM$BYO7_f9Cc0gF zVTR3=rN5MiQxkC!Gj!6?b+fP~FU?zv>2U~R=D4%GwqM8MbV5^`^X3iF6_YpC@l}(| z7hWOVIoX$10@ao0$=x0^WA59Psm6nx;%!oE4KeUf8 z_j8Hp#zuuQ(TQfe{LofN{AjF4#S&ZF-{gzGr=0poaQxb#REKd-ZzCwgYpdsuz;qrC zDzE2%ch#>Qs)Al!o%?BG8g2Ne=|=P=auJoo4Ta8p(;H3s%)C7L_Lds5TDF>dyG_^Q zRIQy1l#U`w(k~U)!yR1K&7{qbVScYN;k&qZ)fw?yeBFd36zv_1<*paI3CE+C@8^qU z>pWk}s54ob@_$fMQ&I0^etU}Q-LFe-4XZ0K-_9YgAl$ffoWFGMKo9n!9Q_V=p`in& z44@?MpaEkK&Z0aaGYfsm?INKWTZ zXdO;Y7mR6LOkUM4(U(qQyik8Is06igVk~}@LxqE&Jl>FHE*55tN!WT2Nmy^nx zo|>c8*nTk;*W{HN%6Kk(;rk5?b!aqiXe9icF=3RId)~81P*rVN`&gfiz_>BRtcv`l#vbG{NR#o)C zvsdc;Skkk0B;KJUtn5;8LqrMdV*R3^Y2raM>2c&AxfFe5-{k*JgYpoj5YU z@MMmpfI_Ys62d;=L*yMljHcmfr(ri-7f*xOj)xjNBOU~!QQ7ohKF(_BLVy`s$30U2 z+)|oQlk{}59gl>$YVTnHnze@bi^o072%1yZ4O^szj(^`80!MDKlnkUkLly4|yIy(r z^1ix6a0?8?r2v1aXo_7|Na}t+JRm=-~@_n1u$P#mzbq`NUu{>-gtz5*Jzt0?n z&Tq91KL#+J^WnJ|lzTesVWkw{SoI>3^l6_A!dZMEid?prkGqk2&F{rEPGXH`5z0@X zk%t5>1cqj53m;rpFZ-Zal@dk;fUC5G7CRd3rCyO%p>N9U|mGxONV0txXH!o`je}P|Z zXrLZO>Rzb81WSLtTrfN*l-)pgY<@PB#60~7-+ga8YbD{VtM04of3|zAp+7Bf2JO zTiGi3=ekBxC8LjunBjD*b(^H!@wVLwGb_k;5=H0Nfp|IEOcaF}a>nuR1jNjkSr|$b zae=4?5e<|B;dI&s?qAA(csFuZ+RM*(ZdT&e3{sZ2O)}*th&c&~)g=q-gN@eL=g1bc z6u7Yx;l2Jcol+HNyzwfM4x@Lk{UW}*${700NbKOm7z}U$J7Sg-#c|ak;9gc|P&{ZR`oZ@hJZVR8b|=BxEFH{%+cY^h###MugwfOD`czsL5kwY|LnE zz@TSn$il(IY|P32o%YGh#AayBuBXq)%*M+1f9|3E-=Kd6`aeL(Lh)<=fWF47$!zG7*bLZ IIZ>GZ2hu}Q)Bpeg literal 0 HcmV?d00001 diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index e376a8301..f03a360a9 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -51,6 +51,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { event ModuleVerified(address indexed _moduleFactory, bool _verified); // Emit when a ModuleFactory is removed by Polymath event ModuleRemoved(address indexed _moduleFactory, address indexed _decisionMaker); + // Emit when ownership gets transferred + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /////////////// //// Modifiers @@ -374,6 +376,16 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { set(Encoder.getKey("polyToken"), IPolymathRegistry(_polymathRegistry).getAddress("PolyToken")); } + /** + * @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 onlyOwner { + require(_newOwner != address(0), "Invalid address"); + emit OwnershipTransferred(owner(), _newOwner); + set(Encoder.getKey("owner"), _newOwner); + } + /** * @notice Gets the owner of the contract * @return address owner diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 65197882c..47e735613 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -438,10 +438,18 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { uint counter = 0; // accessing the data structure userTotickers[_owner].length bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); - 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)) { + counter ++; + } + } + bytes32[] memory tempList = new bytes32[](counter); + counter = 0; + 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)) { tempList[counter] = tickers[i]; counter ++; 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/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; + } +} diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index a5b4972d7..a5f365050 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -25,9 +25,9 @@ contract MockBurnFactory is TrackedRedemptionFactory { * @return Address Contract address of the Module */ function deploy(bytes /*_data*/) external returns(address) { - _takeFee(); + address polyToken = _takeFee(); //Check valid bytes - can only call module init function - MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender); + MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, 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/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol index 311ffbf0c..8f7abfb80 100644 --- a/contracts/mocks/MockRedemptionManager.sol +++ b/contracts/mocks/MockRedemptionManager.sol @@ -15,8 +15,8 @@ contract MockRedemptionManager is TrackedRedemption { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - TrackedRedemption(_securityToken) + constructor (address _securityToken, address _polyToken) public + TrackedRedemption(_securityToken, _polyToken) { } diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 9a804772f..9d2bcef8a 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 7ce4dd3c5..6f1f21428 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 "openzeppelin-solidity/contracts/token/ERC20/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, @@ -48,8 +47,8 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } @@ -67,8 +66,8 @@ contract ERC20DividendCheckpoint is DividendCheckpoint { address _token, uint256 _amount, bytes32 _name - ) - external + ) + external withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); @@ -132,16 +131,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); } @@ -157,15 +156,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"); @@ -209,7 +208,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 073ba7e1f..502ad6b80 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,21 +8,26 @@ import "../ModuleFactory.sol"; */ contract ERC20DividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_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; } /** @@ -30,8 +35,8 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @return Address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender); + address polyToken = _takeFee(); + address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, 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 06321fdb7..eee93e587 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, @@ -28,8 +29,8 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } @@ -55,7 +56,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _checkpointId, bytes32 _name - ) + ) external payable withPerm(MANAGE) @@ -75,7 +76,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, address[] _excluded, bytes32 _name - ) + ) public payable withPerm(MANAGE) @@ -93,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 @@ -115,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"); @@ -168,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 955d5c629..f51677d00 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,21 +8,26 @@ import "../ModuleFactory.sol"; */ contract EtherDividendCheckpointFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_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; } /** @@ -30,8 +35,8 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender); + address polyToken = _takeFee(); + address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, 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/Experimental/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol index aaf4b6db7..5e34bbaba 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -19,8 +19,8 @@ contract TrackedRedemption is IBurn, Module { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } diff --git a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol index 2cfaaa6fc..f2b18ee4d 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol @@ -30,8 +30,8 @@ contract TrackedRedemptionFactory is ModuleFactory { * @return Address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address trackedRedemption = new TrackedRedemption(msg.sender); + address polyToken = _takeFee(); + address trackedRedemption = new TrackedRedemption(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(trackedRedemption), getName(), address(this), msg.sender, setupCost, now); return address(trackedRedemption); diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index 5c152982b..13bc29d18 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -33,8 +33,8 @@ contract ScheduledCheckpoint is ICheckpoint, ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol index 3e41ef5f0..6ef2fc34a 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol @@ -30,8 +30,8 @@ contract ScheduledCheckpointFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address scheduledCheckpoint = new ScheduledCheckpoint(msg.sender); + address polyToken = _takeFee(); + address scheduledCheckpoint = new ScheduledCheckpoint(msg.sender, polyToken); emit GenerateModuleFromFactory(scheduledCheckpoint, getName(), address(this), msg.sender, setupCost, now); return scheduledCheckpoint; } diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 57ad67642..1397ad832 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -54,9 +54,9 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) + constructor (address _securityToken, address _polyToken) public - Module(_securityToken) + Module(_securityToken, _polyToken) { } @@ -129,7 +129,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { 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 == _startTimes.length && _userAddresses.length == _totalAmounts.length, "Input array length mismatch" ); diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol index 69d4a0e63..d751f0b1c 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol @@ -30,8 +30,8 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender); + address polyToken = _takeFee(); + LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(lockupVolumeRestrictionTransferManager), getName(), address(this), msg.sender, now); return address(lockupVolumeRestrictionTransferManager); diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol index 684840a7a..6406dd013 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol @@ -46,8 +46,8 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor(address _securityToken) public - Module(_securityToken) + constructor(address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol index 8c5eb20ce..4e2b1ff1b 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol @@ -32,8 +32,8 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); - SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender); + address polyToken = _takeFee(); + SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender, 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"); diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index fc79af511..aae15670a 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -4,30 +4,22 @@ import "../RegistryUpdater.sol"; import "../interfaces/IModule.sol"; import "../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/token/ERC20/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 */ - constructor (address _securityToken) public { - securityToken = _securityToken; - factory = msg.sender; - polyToken = IERC20(RegistryUpdater(_securityToken).polyToken()); + constructor (address _securityToken, address _polyToken) public + ModuleStorage(_securityToken, _polyToken) + { } //Allows owner, factory or permissioned delegate diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index 471ac2eca..adc4432b6 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -163,11 +163,14 @@ contract ModuleFactory is IModuleFactory, Ownable { return name; } - function _takeFee() internal { + function _takeFee() internal returns (address) { + address polyToken = RegistryUpdater(msg.sender).polyToken(); + require(polyToken != address(0), "Invalid POLY token"); if (setupCost > 0) { - require(IERC20(RegistryUpdater(msg.sender).polyToken()).transferFrom(msg.sender, owner(), setupCost), + require(IERC20(polyToken).transferFrom(msg.sender, owner(), setupCost), "Insufficient allowance for module fee"); } + return polyToken; } } diff --git a/contracts/modules/ModuleStorage.sol b/contracts/modules/ModuleStorage.sol new file mode 100644 index 000000000..fd9307934 --- /dev/null +++ b/contracts/modules/ModuleStorage.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; + +/** + * @title Storage for Module contract + * @notice Contract is abstract + */ +contract ModuleStorage { + + 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 { + securityToken = _securityToken; + factory = msg.sender; + polyToken = IERC20(_polyAddress); + } + +} diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index f79941a6a..7dca72ce5 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -8,7 +8,7 @@ import "../Module.sol"; */ contract GeneralPermissionManager is IPermissionManager, Module { - // Mapping used to hold the permissions on the modules provided to delegate, module add => delegate add => permission bytes32 => bool + // Mapping used to hold the permissions on the modules provided to delegate, module add => delegate add => permission bytes32 => bool mapping (address => mapping (address => mapping (bytes32 => bool))) public perms; // Mapping hold the delagate details mapping (address => bytes32) public delegateDetails; @@ -26,8 +26,8 @@ contract GeneralPermissionManager is IPermissionManager, Module { /// @notice constructor - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } @@ -243,7 +243,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { function getAllDelegates() external view returns(address[]) { return allDelegates; } - + /** * @notice Returns the Permission flag related the `this` contract * @return Array of permission flags diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index 011da5c3e..a353b7e26 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -30,8 +30,8 @@ contract GeneralPermissionManagerFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address permissionManager = new GeneralPermissionManager(msg.sender); + address polyToken = _takeFee(); + address permissionManager = new GeneralPermissionManager(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); return permissionManager; diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index e77e98701..17c4da3e2 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -13,9 +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 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; @@ -31,8 +33,8 @@ contract CappedSTO is ISTO, ReentrancyGuard { event SetAllowBeneficialInvestments(bool _allowed); - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } @@ -48,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 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 */ @@ -64,6 +66,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 +111,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 +125,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)); } /** @@ -153,10 +157,11 @@ 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 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. + * @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) { @@ -180,11 +185,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 +216,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 +267,23 @@ 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); + _tokens = _tokens.div(uint256(10) ** 18); + uint256 granularity = ISecurityToken(securityToken).granularity(); + _tokens = _tokens.div(granularity); + _tokens = _tokens.mul(granularity); + _refund = _investedAmount.sub((_tokens.mul(uint256(10) ** 18)).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/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index b7d548b8e..25f02cd8b 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -21,7 +21,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)); } @@ -31,9 +31,9 @@ contract CappedSTOFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); + address polyToken = _takeFee(); //Check valid bytes - can only call module init function - CappedSTO cappedSTO = new CappedSTO(msg.sender); + CappedSTO cappedSTO = new CappedSTO(msg.sender, 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*/ diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index b4a25e1a6..ad6bb6f74 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -23,8 +23,8 @@ contract DummySTO is ISTO { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index b94fd747d..dc2f9dd56 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -31,9 +31,9 @@ contract DummySTOFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); + address polyToken = _takeFee(); //Check valid bytes - can only call module init function - DummySTO dummySTO = new DummySTO(msg.sender); + DummySTO dummySTO = new DummySTO(msg.sender, 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*/ diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/ISTO.sol index 111c6fa4c..8e162574b 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 "openzeppelin-solidity/contracts/token/ERC20/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/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 0c9da3db0..5290a9e38 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -20,8 +20,8 @@ contract PreSaleSTO is ISTO { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) public - Module(_securityToken) + constructor (address _securityToken, address _polyToken) public + Module(_securityToken, _polyToken) { } diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index ca587af00..29aabbe7e 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -32,9 +32,9 @@ contract PreSaleSTOFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); + address polyToken = _takeFee(); //Check valid bytes - can only call module init function - PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender); + PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender, 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*/ diff --git a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol deleted file mode 100644 index d8990d796..000000000 --- a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol +++ /dev/null @@ -1,32 +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 _factoryAddress Contract address of the factory - * @return address Address of the deployed STO - */ - function deploySTO(address _securityToken, address _factoryAddress) external returns (address) { - address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _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 437aede7b..33c9bacfa 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -7,82 +7,16 @@ import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/utils/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 // - ///////////// - - 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; - - // 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) 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 - uint8 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; - - // Whether or not the STO has been finalized - bool public isFinalized; - - // Final amount of tokens returned to issuer - uint256 public finalAmountReturned; + string public constant POLY_ORACLE = "PolyUsdOracle"; + string public constant ETH_ORACLE = "EthUsdOracle"; //////////// // Events // @@ -97,7 +31,7 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _tokens, uint256 _usdAmount, uint256 _tierPrice, - uint8 _tier + uint256 _tier ); event FundsReceived( address indexed _purchaser, @@ -108,16 +42,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 ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint256 _latestTier); event SetAddresses( address indexed _wallet, address indexed _reserveWallet, @@ -143,19 +68,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"); _; } @@ -163,11 +88,10 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // STO Configuration // /////////////////////// - constructor (address _securityToken, address _factory) public Module(_securityToken) { - oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; - oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; - require(_factory != address(0), "In-valid address"); - factory = _factory; + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { } /** @@ -197,69 +121,125 @@ 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); + 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); + // NB - _setFundRaiseType must come before modifyAddresses + _setFundRaiseType(_fundRaiseTypes); + _modifyAddresses(_wallet, _reserveWallet, _usdToken); + _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } - function modifyFunding(FundRaiseType[] _fundRaiseTypes) public onlyFactoryOrOwner { + /** + * @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 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); - } } + /** + * @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 - ) public onlyFactoryOrOwner { + ) external onlyOwner { + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO already started"); + _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, + uint256[] _tokensPerTierTotal, + uint256[] _tokensPerTierDiscountPoly + ) external onlyOwner { + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO already started"); + _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 + ) external onlyOwner { + /*solium-disable-next-line security/no-block-members*/ + require(now < startTime, "STO already started"); + _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, + address _usdToken + ) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO shouldn't be started"); + 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( + function _modifyTiers( uint256[] _ratePerTier, uint256[] _ratePerTierDiscountPoly, uint256[] _tokensPerTierTotal, uint256[] _tokensPerTierDiscountPoly - ) public 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"); + ) 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.push(Tier(_ratePerTier[i], _ratePerTierDiscountPoly[i], _tokensPerTierTotal[i], _tokensPerTierDiscountPoly[i], 0, 0)); } - ratePerTier = _ratePerTier; - ratePerTierDiscountPoly = _ratePerTierDiscountPoly; - tokensPerTierTotal = _tokensPerTierTotal; - tokensPerTierDiscountPoly = _tokensPerTierDiscountPoly; emit SetTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); } - function modifyTimes( + function _modifyTimes( uint256 _startTime, uint256 _endTime - ) public onlyFactoryOrOwner { - /*solium-disable-next-line security/no-block-members*/ - require((startTime == 0) || (now < startTime), "Invalid startTime"); + ) internal { /*solium-disable-next-line security/no-block-members*/ require((_endTime > _startTime) && (_startTime > now), "Invalid times"); startTime = _startTime; @@ -267,16 +247,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; @@ -298,12 +276,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"); @@ -334,7 +312,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]); } @@ -358,16 +336,32 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { * @notice fallback function - assumes ETH being invested */ function () external payable { - buyWithETH(msg.sender); + buyWithETHRateLimited(msg.sender, 0); + } + + // Buy functions without rate restriction + function buyWithETH(address _beneficiary) external payable { + buyWithETHRateLimited(_beneficiary, 0); + } + + function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) external { + buyWithPOLYRateLimited(_beneficiary, _investedPOLY, 0); + } + + function buyWithUSD(address _beneficiary, uint256 _investedDAI) external { + buyWithUSDRateLimited(_beneficiary, _investedDAI, 0); } /** * @notice Purchase tokens using ETH * @param _beneficiary Address where security tokens will be sent + * @param _minTokens Minumum number of tokens to buy or else revert */ - function buyWithETH(address _beneficiary) public payable validETH { + function buyWithETHRateLimited(address _beneficiary, uint256 _minTokens) public payable validETH { 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"); // Modify storage investorInvested[_beneficiary][uint8(FundRaiseType.ETH)] = investorInvested[_beneficiary][uint8(FundRaiseType.ETH)].add(spentValue); fundsRaised[uint8(FundRaiseType.ETH)] = fundsRaised[uint8(FundRaiseType.ETH)].add(spentValue); @@ -382,24 +376,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 _minTokens Minumum number of tokens to buy or else revert */ - function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) public validPOLY { - _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY); + function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minTokens) public validPOLY { + _buyWithTokens(_beneficiary, _investedPOLY, FundRaiseType.POLY, _minTokens); } /** - * @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 + * @param _minTokens Minumum number of tokens to buy or else revert */ - function buyWithUSD(address _beneficiary, uint256 _investedDAI) public validDAI { - _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI); + function buyWithUSDRateLimited(address _beneficiary, uint256 _investedDAI, uint256 _minTokens) public validDAI { + _buyWithTokens(_beneficiary, _investedDAI, FundRaiseType.DAI, _minTokens); } - 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 _minTokens) internal { + require(_fundRaiseType == FundRaiseType.POLY || _fundRaiseType == FundRaiseType.DAI, "Invalid raise type"); + uint256 initialMinted = getTokensMinted(); uint256 rate = getRate(_fundRaiseType); (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); @@ -424,40 +422,29 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { internal nonReentrant whenNotPaused - returns(uint256, uint256) + returns(uint256 spentUSD, uint256 spentValue) { if (!allowBeneficialInvestments) { - require(_beneficiary == msg.sender, "Beneficiary does not match funder"); + require(_beneficiary == msg.sender, "Beneficiary != funder"); } - require(isOpen(), "STO is not open"); - require(_investmentValue > 0, "No funds were sent"); - - uint256 investedUSD = DecimalMath.mul(_rate, _investmentValue); - uint256 spentValue = investedUSD; - - // Check for minimum investment - require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + uint256 originalUSD = DecimalMath.mul(_rate, _investmentValue); + uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); - // 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"); - 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++) { + bool gotoNextTier; + uint256 tempSpentUSD; // Update current tier if needed if (currentTier != i) currentTier = i; // If there are tokens remaining, process investment - if (mintedPerTierTotal[i] < tokensPerTierTotal[i]) - spentUSD = spentUSD.add(_calculateTier(_beneficiary, i, investedUSD.sub(spentUSD), _fundRaiseType)); - // If all funds have been spent, exit the loop - if (investedUSD == spentUSD) - break; + if (tiers[i].mintedTotal < tiers[i].tokenTotal) { + (tempSpentUSD, gotoNextTier) = _calculateTier(_beneficiary, i, allowedUSD.sub(spentUSD), _fundRaiseType); + spentUSD = spentUSD.add(tempSpentUSD); + // If all funds have been spent, exit the loop + if (!gotoNextTier) + break; + } } // Modify storage @@ -468,52 +455,143 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } - // Calculate spent in base currency (ETH, DAI or POLY) - if (spentUSD == 0) { - spentValue = 0; - } else { - spentValue = DecimalMath.mul(DecimalMath.div(spentUSD, spentValue), _investmentValue); + spentValue = DecimalMath.div(spentUSD, _rate); + } + + /** + * @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 || _fundRaiseType == FundRaiseType.ETH, "Invalid raise type"); + uint256 rate = getRate(_fundRaiseType); + 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++) { + 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, allowedUSD.sub(spentUSD), _fundRaiseType); + spentUSD = spentUSD.add(tempSpentUSD); + tokensMinted = tokensMinted.add(tempTokensMinted); + // If all funds have been spent, exit the loop + if (!gotoNextTier) + break; + } } - // Return calculated amounts - return (spentUSD, spentValue); + spentValue = DecimalMath.div(spentUSD, rate); + } + + function _buyTokensChecks( + address _beneficiary, + uint256 _investmentValue, + uint256 investedUSD + ) + internal + view + returns(uint256 netInvestedUSD) + { + 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( address _beneficiary, - uint8 _tier, + uint256 _tier, uint256 _investedUSD, 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; + 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, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, totalRemaining, investedUSD, _tier); else - (spentUSD, tierPurchasedTokens) = _purchaseTier(_beneficiary, ratePerTierDiscountPoly[_tier], discountRemaining, investedUSD, _tier); + (spentUSD, tierPurchasedTokens, gotoNextTier) = _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 && + tierData.tokenTotal.sub(tierData.mintedTotal) > 0 && + (_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); + tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); + tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); + } + } + + 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) && (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.add(tokensMinted)) > 0 && + (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) + ) { + (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTierAmount(tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), _investedUSD); spentUSD = spentUSD.add(tierSpentUSD); - mintedPerTier[uint8(_fundRaiseType)][_tier] = mintedPerTier[uint8(_fundRaiseType)][_tier].add(tierPurchasedTokens); - mintedPerTierTotal[_tier] = mintedPerTierTotal[_tier].add(tierPurchasedTokens); + tokensMinted = tokensMinted.add(tierPurchasedTokens); } - return spentUSD; } function _purchaseTier( @@ -521,14 +599,31 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { uint256 _tierPrice, uint256 _tierRemaining, uint256 _investedUSD, - uint8 _tier + uint256 _tier + ) + internal + returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) + { + (spentUSD, purchasedTokens, gotoNextTier) = _purchaseTierAmount(_tierPrice, _tierRemaining, _investedUSD); + if (purchasedTokens > 0) { + 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 - returns(uint256, uint256) + view + returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); - uint256 spentUSD; - uint256 purchasedTokens; + 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 @@ -536,13 +631,11 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { spentUSD = _investedUSD; } purchasedTokens = _tierRemaining; + gotoNextTier = true; } else { - spentUSD = _investedUSD; + 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); } ///////////// @@ -575,9 +668,13 @@ 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); } + /** + * @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(); @@ -629,30 +726,59 @@ 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; } /** - * @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) { 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; } + /** + * @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 + * @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 */ function getNumberOfTiers() public view returns (uint256) { - return tokensPerTierTotal.length; + return tiers.length; } /** @@ -663,6 +789,42 @@ 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. + * @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[]) { + 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, + currentTier, + cap, + rate, + fundsRaisedUSD, + investorCount, + getTokensSold(), + _fundRaiseTypes + ); + } + /** * @notice This function returns the signature of configure function * @return bytes4 Configure function signature diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4b9cde788..b55b7bb81 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,21 +10,20 @@ import "../../libraries/Util.sol"; */ contract USDTieredSTOFactory is ModuleFactory { - address public USDTieredSTOProxyAddress; + address public logicContract; /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module - * @param _proxyFactoryAddress Address of the proxy factory */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _proxyFactoryAddress) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { - require(_proxyFactoryAddress != address(0), "0x address is not allowed"); - USDTieredSTOProxyAddress = _proxyFactoryAddress; - version = "1.0.0"; + require(_logicContract != address(0), "0x address is not allowed"); + logicContract = _logicContract; + version = "2.1.0"; name = "USDTieredSTO"; title = "USD Tiered STO"; /*solium-disable-next-line max-len*/ @@ -37,12 +37,10 @@ contract USDTieredSTOFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); - 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(this)); + address polyToken = _takeFee(); + address usdTieredSTO = new USDTieredSTOProxy(msg.sender, 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..919fd2900 --- /dev/null +++ b/contracts/modules/STO/USDTieredSTOStorage.sol @@ -0,0 +1,82 @@ +pragma solidity ^0.4.24; + +import "openzeppelin-solidity/contracts/token/ERC20/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; + +} diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 1d4e2ce1b..1d11f6865 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -18,19 +18,21 @@ contract CountTransferManager is ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) + constructor (address _securityToken, address _polyToken) public - Module(_securityToken) + Module(_securityToken, _polyToken) { } /** @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 */ ) @@ -40,7 +42,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 c61d42ab4..7f16203da 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -18,7 +18,7 @@ contract CountTransferManagerFactory is ModuleFactory { constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.1.0"; name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; @@ -32,8 +32,8 @@ contract CountTransferManagerFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); - CountTransferManager countTransferManager = new CountTransferManager(msg.sender); + address polyToken = _takeFee(); + CountTransferManager countTransferManager = new CountTransferManager(msg.sender, 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"); diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 9e856243b..7b830d375 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, @@ -69,9 +45,9 @@ contract GeneralTransferManager is ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) + constructor (address _securityToken, address _polyToken) public - Module(_securityToken) + Module(_securityToken, _polyToken) { } @@ -82,6 +58,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 @@ -167,16 +154,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; } @@ -199,9 +195,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); } @@ -225,7 +247,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]); } } @@ -266,10 +288,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); } /** @@ -288,8 +307,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*/ } /** @@ -300,6 +318,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 03168efb1..cfebe557c 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,21 +8,26 @@ import "../ModuleFactory.sol"; */ contract GeneralTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_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,8 +36,8 @@ contract GeneralTransferManagerFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address generalTransferManager = new GeneralTransferManager(msg.sender); + address polyToken= _takeFee(); + address generalTransferManager = new GeneralTransferManagerProxy(msg.sender, 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/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index f59590828..621161a32 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -65,9 +65,9 @@ contract ManualApprovalTransferManager is ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) + constructor (address _securityToken, address _polyToken) public - Module(_securityToken) + Module(_securityToken, _polyToken) { } @@ -112,7 +112,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"); @@ -128,7 +127,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"); @@ -143,7 +141,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); @@ -155,7 +152,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); diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 7c121e112..fe4d532dd 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -17,7 +17,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_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"; @@ -30,8 +30,8 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes /* _data */) external returns(address) { - _takeFee(); - address manualTransferManager = new ManualApprovalTransferManager(msg.sender); + address polyToken = _takeFee(); + address manualTransferManager = new ManualApprovalTransferManager(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(manualTransferManager); diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index cea576fb7..61cbf437a 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -1,7 +1,7 @@ /** - * DISCLAIMER: Under certain conditions, the limit could be bypassed if a large token holder - * redeems a huge portion of their tokens. It will cause the total supply to drop - * which can result in some other token holders having a percentage of tokens + * DISCLAIMER: Under certain conditions, the limit could be bypassed if a large token holder + * redeems a huge portion of their tokens. It will cause the total supply to drop + * which can result in some other token holders having a percentage of tokens * higher than the intended limit. */ @@ -42,9 +42,9 @@ contract PercentageTransferManager is ITransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken) + constructor (address _securityToken, address _polyToken) public - Module(_securityToken) + Module(_securityToken, _polyToken) { } diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 624de7212..3f858ade0 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -32,8 +32,8 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @return address Contract address of the Module */ function deploy(bytes _data) external returns(address) { - _takeFee(); - PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender); + address polyToken = _takeFee(); + PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender, 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"); 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/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol new file mode 100644 index 000000000..c0f4c4201 --- /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/utils/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/docs/images/Core Architecture 2.0.0 Diagram.png b/docs/images/Core Architecture 2.0.0 Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e227d159cf33682adf4961d61416ac6b76a8578d GIT binary patch literal 60316 zcmeFZ2UJsAw;T_cWE6k8m9U zfk4bEcW-HfKu4$`5dGRATHpD^!ngSECVsCG_~N#V=ns zcXe<3)*Dv680UWyc%B9T`=9h5iE{!@Ik`W%v9rgrV=o8~F-}i1N^JVd<<{%~tP;q< zQSE2qCo~)oM>qcQoVgbh@Y0-CXgba=Lw9$n0OzXgWGuuOJ4Y@Uul!~zqSq?lS_?ok zG_jPh+i*Ib52--cdrhC>(z-5#I9lkwT4vq52sr_K@kCs+ZC>%q3@TNM;1`w8`^)|8 za;I!nude{MNIRvFjBT~DMQgJqfv0Q@$NfvHGxZ?V-nl@>qpt<^z=->OQ&B!Bjo!qX z?u*k6Ec-*IUC1iR%@GSc8t*ZXQGagI_W%e)t?l9!h~uz`IR3EuBY7dex+W2TA4n_W zWZzMB+WWOM#HPfz()%XR-{oF0-5n_&61J4GRDU|18x@EE-UbR^RM%&+KmF-!z6!aK z7y-P(3fS$AZ8(4A+DjZc%V-tY z+$d8q&i1p? zBjNKKUvpH`C{6JauilvKBe;!$GwCOkncxR8ukF0}rOC%0sBY|JW~ih)P-uU zxasX~`0o=-0&(&1Pl($x=bMh-$YnUTR<&bLc{EA$Iy}tH@4AgyN_Ph)&cA*7@k0&L zJ~D2m9(i8OYZY~pBB%?CP7Uv8dHc14#p)-Nl_Sr+49Mh{I4!zyKfn44hv6>!!TvM#<Pc(YgaI@=>r@Z?vF=B%EytF0j>T4Dt zfn>!bfgc<=HW!RdOi0!6Oa&tk64zWwWXqibZ^^tvn0?@J2ZO-ReF?Yjo6h)K@5Qnw zUPv_QREo8igm~XiU(w|gDXA6jxReXcRTa`$sR}P#?en@E%v_|AuxWpJRWfFeRjx%q zPr^4%LK2oEFFtLZGp{?7S*Qyh)BQ<)V|KU$;ZE?N&%1Ml3G60cdgVvwJ4WZ+t@)Np zpebq|P;1=Oq}Y(1ZHk^x4?c|WZDO=Gm2OybQ}3K5k9K@1rSnrIb6M5Pj!D&#Wmegt zs-ixFnPti%12B2$P&5`l5B>NdEMFr9kHzDtMs{JPA?ib5=?{0}I|^PSFM!|I%i~R> z?Q=BF#K|2u*BfigBQR+^aqfIl8P{PdRi!m`M}RCcx|UopNg@A)$q;0aVQ0U&(1c?t z)vGGrDvi6&;v>!~h$@i|7d##*uI8BH8Dua+TxkC$csxrQ+q5C&HCwEXi?(Z3X-0gE4A9B*c=jtM_xR6;tubUGPkws#oL7O6g+6<7pey^FFOo)H^+$ z?;MW9Cu?DXRF+B3(;Yi_j`=ffD=i%#meO6{7fM(RO*?W9Qv=?f`zb58E#YT55pOe< z9Tmx|AEIh7FdA6lj>LsAM$9Yug{SA=$KkDc27LNCUTH`B$!*r69>JL~Ld&Soef>0M zVMjtwatH>qh^3yCom=?gL~=qib!dz+VF$&Bb-d51UjNCW!ZauUsV)3xRN3gN-2zCNn&+z&d=%- zv2y1L9LsNYAD{|T4r7Yt#+-H5t27DzhzF>TnhRY|^w)eY8dSQ_@-MDUBZMb@#i!Q6 zM*OFy*Um~wGdhxM@vJ`tN3vG(yfkIWnK^5Jx-!)i#^>2yXW@~-KecJC_<5nZ&x?c= zsck@=2lo9x*IFj$&P%IAmr^v|>K@$%Kx4P^jwpYjQo> zdPL(_y{bnG%Z+VCTNj}9g+`m~3iWbJxqI(zNX%P2v!Vt+FV!|)H$LN1(xmtN@DGjf zZ~$vEue#K)lIC&jw(8K$oSiGwjor^o{`|t|#qj}uGmls?a&C3-4_!T5qD>NIOaJ1@ zecMy4+R2^p=9z=D2kszIzkSl_xH77JNM2iW$IHDsb@R}!%z0)Ih^EBb7n>~A-TQV` z?D>O{dXZ{)%pH1}H*e*Z#`UU}7Oyy2l49}bt&z4alI7au+l{?88c<+2PELW;_1xC( z3pp=(E?Dz8CyDg2;M7%@u$|Yc&@8nE3 zsBNFnOU|?~-7md-6<#j_c-YOjK%kEw0my?)mcPpHv?elZ;O;_qn7I+sf@BoMo#?;FpyuD?YSN5x0akF`I( zx3DM!pr-aJU?GJ#ZPo+45aThbmWbolh>e|;>Q`N5sg&oty?ig*K1x~59qc(|6@Em4 zC+p9Xx212Ch?S(&B8tKUxN}q&whfn;z_^#vZ-Mx{` z{`hKO?^27g+8%yxJJ&o}tKiV3 z5iJ-=uU$T~%q;iDamNb;lIITEH2)2-iF~%;zdE0{}eownFf}Q-u^Jq#J0cy!VVt7Fu2FPg~tWRFX1OtAf)`vA%Avw4Di*KE1<3BWXCX>-WVb;q!+4<6Z=n>#2^^eC&%*BSkRAhg2~(j?oh{zf7O$ zZDfyNt4uX;Gic58%@AyAimjgH>WSa9$KO~7-{iun8y8l&mL=O|6y#b^SOJ`Co%!pK zVcPM}?9XN#4xc*($NO>x-NW;KfWRng8H^a@AvwYu8p`KLaUHOnaou5ztD@#Wbxp~D zhxePOdc*pHeOAuSy=7wMu&cbK`kHL)I<`p?G@#Sx>4<+2dinivxJGnGN9UkmSHo=$ z19dOW_I71I=&DF&@ZR|it=+*Rp%GvfWZe$7-csvIOScjuL;uN>F&}%i#7eNM<23OH?CB{p8uihq!?;l*1 ze<3Nn`C(;Fx{jUHx)@{-Jz>5&ak;|r+KefOM66nzm!b1+0EyiEHgS|$BnsgpYnLW; zq0h~)hvY?V+cQ6$GjBsg(tZ)#vauwQ)8;O$(j3ORm6uA|XU=kOP-s9mZvJHids>*a zcZKRR4@>xDd!-Kp@`3}021JIJwou_AS%ZX@3v493dAidVU5RQxK|BI3*$engzN%Ku zKfEL)MmRe+?Qz_aR6{rCdIv4nv4lw#0SxKCV#$f5Avh3+;vP6ioN_x?G9zmCEVC1%D1 z!am)H9sTxH>U(}xe`#u)rv5eYo8D}2*hYr*klL0Pg`QY#WnxA=>l*ql0(X9H9gjuC z+{-eGL;B%OX<@!j1D)5nGX4A&@;~_~nSij@j=@=HmcH(|oG4e;OYRiz{^XE*fA|2M z7_|%;m}t651vt5e^AnzMkoa|_N)EJy6xh zkZQ?!5QI5OL#cmL8h!B5y?cqtvTXh-!b?yV>8qi~aJCb@|z6Q>wkxcfo z-toaYX5kBcK|_$8ca?O|#M`S45VL&FO;D~t@>4?9{liACoC{C)?bY#zr<_oN_R}}mg^B*GAenPC zlmnhiA4`0C4x-QIlaF}o>JZ3;*R$JxB;L&e%^+}9%AIlFJ%~xA>k!4`@sl-0DpY)F z=gTe2m^sHIw`ZPens%4HEuh2_yE;;!n|Lg@nOLABcQQ1Kbp?3^gk?NS<fIyG0lN9m%|I%j^gn` zb{S%}x!QK1@zF8i+N+QR+)<;p{xiy(;r(I=Utr8q$HIxSrvpxF0p+0O<53$LdJH*O6HB!8x)pM{wI2 zqa^j)Vf?HWm3jHskAiyytrG~L8i=Hr=-pboc){GioyOg^m#ZRw0~*Yxb||0k*5`#K zv*{ZyvIob{wJjfv_xDkhTs7VhMTVZzFXsPkYrk{VW^uRGuiLiL8*ngSZHvgn7Gm*A z#m1gh?QF^DZ+kcF$ql8G4`jlh12Gp^J|s@gXbEgX+hMsVXyxJ&CtkN->)QZ zd0wZzHG7RzAFaH{)}1h;^Z>k{!PXLN>i)a+b|Zac`l{XPCLC& z=wojKE;)36IML3vE@!+OcjO9;E)2T^A7^$wV5&fsrf`Vty^UK?;#F{;c@ibuZ%>|H z>o6QN94x!B`|T*4)-$e1nb{98S@V@LOD=Jnn4g^wwRXA|C#BTi%^C#0muJvBcNBDtV${f7B-N00?gF zSPcfwoyyD~e`ngR;~O8Yzj2}mkz$JhKG(M>)QGO$QRxk6Hm#-TDQDN0gbdpN{sK{s9)2z_zW-8DaQdPu;5g))ktI%rrO7B$1u%PRD9tz*W#qcE8!Wv0h!>64qv@< zGf>!Zx1oyzu_NDIR-K89w8T<+1Y>b0T;WnyrcnA$Z zi3TYzML2nS-f-w96NVf$6Fh7-0y=+ioLVA79;+F^+f22 zy@Er!w%Hg=*(CRoYf<^g_gqRxFhV(*5{GUG_w8s#w^$K+HF2s>%O-g;u?`Q`NMcuD z{4s#r$Gc@px!8<(;|>WjW)v48T6Apv6RM1-J%N9IHWbVK;RG!#-BV{ln+7(SmR}iP zCKjy7)%#gvt1OW?l$~fd`q*l$_s-Z?+4uFe>YhD-r2uINX&olObDsIz7lHpl0P|15 z(~X}>UOf(HL%OMf8}wPu<`xEl0qeOk31I-Cfh7yBm^;$KoKhVKh9QYqZoSG|#Ca}w zmL=iogoONq$bZI#13h#^#6)?L4|=WVhJew)bdT%Z;MVj`YmZO(1Baa3I&4M;S-g+7 zCJHd$(01V;V}P=~4>x_Z$HP23^7$xy$UDy3lF{+jZc(0SGioMudrN>yZ{LY^xRE2~ zM2fAcfCwrlNTFchSF}BgEzo4?5ldzG8(pD@D-KQ~h*Mr~Uc_60AUMuT^jN15GJL)1v3 z1l^HoegkCeRNM(1UPEN_lS+|UvcM)5(&)MMlGXoIbcQXjqu%*&B`y@Q?1kalVbU4(xSCK zM(fF0pzlZ9ahBbtgZjP0A!IqNSf5kMX4g~c##SSWt}AIVV{n+Z=at$q_B~VHL*cbO z7o^Iv45hQ26#UN?`RR-(bT}s4BQY|k^u&-UtxB>SA4bF4(!_fgUeATPJG`!~ z_0I7;F(CWhW@g?lH(ZoPSzgqUGUK&Q(5lVs7j+sb^1kWf_xm1ow$uo6qcM$~s=^Xk zK5Jt#E^&L6fb3?(88%Ezmc}S{IA%lRm}y^qsdZ#4xyKZ4w&Da*i!kMwv2{zPga(0M zwe+6ALCWO&gifV6h4I)M4ccF5tgeKJKSFJN)S+t>6**Gm+jn6+TR${ zORqtS@Evxx;v7yW4I7wlAr~AX-}mnObr0UQa|Bd5VrLS?b2b;x%qQ&SUG_~KCo}h8 zYh`I*ym8iyAEQE{S$uB{NXpFAJ4L4rpT>OY* zMwDL`6fPXTQbrIbU9yPe;>qZ=B<1TSP758d@=5jF2dEkd zHov{FZ?@l3OCbre5JJb@$IYi7J!@&dLS?A}uSWT_KACxk0+;ZbMVSW7ws_jlZa?x0 zKBLNM)gvsSwyGAd@m#f?%20AX;T&dYi;A&eao|!{YfdRE<3{TCWK8}NIv4>jVzhR= zk$B0nkHX_RduH#=^k^=d&a8Vx_7egm`81f3Y5#$ zW#A%s$L%F>(@zP5IQ2~WO0ce2*TJ?Y#coIL34Lo4GR#D+q91lj7gaK2WVK=%ZjW6c zzO0jt5Z7G19G^Dl=B`5n!zW@KCLB5AneByP8PT^if`xn4)G7Ga^Xd6K2F7t1KekpaVNkI@!KWHhHO+qe$PNN|YV=z()?`lFtvwON>=tAI?N1yU!qwIb)V}0z zg)!X8Rm=I{!P_i7WiW#j+L6nhi|nk99_iJuG`p|}V`zLcEp|cdMKWGXny=L6kzEBd zCZk5GC5@9xnKCI+_H4-FJ<8kEHbJ*t~ZW}$ZV{nvL{-L)20(5j%Cyu*`U6~ZIXvXkb zyYfX4HuDAA&e~! z>pQz>OxQaj8(fQdAOUr!05{o|e{L0bFV!pCGsxR7e0kuyV^ShG$Xoq{P+8R{p_mQr z10^n%b>|nZjA-o)#x^|gPn@9nzMXF=ucrzYmC+$3JM&tH@Y4Gmt)?Ci|9Iy&Qggs1 z30bW!{BUdUWP*usPrajyj))H%JUtKmy-~VyN@)Asv_Gjv-isL%hF8t9n6<}&e(u&{#Y?LIwIv3sgdiq1#!bI~-0a-#f;*e6SLb| zEodn(7aFcmasFStjt;uK#d42kgs`53SC+cG{ka%1Q9o`t_q8_=P5uEWEi7${bun4a z<{^`ZhW=F;Ev&yiXbrHTP3^Y;dWlDl)DiH(gNux~Jo`bDD@!GgqnJIIfzcFpyemww`sP0YIP=vtCsY?^EJ&TD_H~n&n5!>2 zBr8<(U$T%e|F*HIQaR8xd3xtohS%pPg@*2kar7e_S4(&&hsy$%`xkRH&v-!o9D!Ci6TExJiV#pbK zmEAuXUs>TZrYIyV&{Bd+j=LmMDkt2)=1>L1u8r~*V5nih>p1J?)wVM8G~Xfwa%%ujy-SuBu&Q~Rc8qfz!4H&8=t}SN!oVyJu zrJm1bPj$xVpx%RG-uX`fyj!09D7&>LQPGXE@hzy5?u2}e6iaSRXi5<(>dmpsOs+`Q zg;tlsv{JRNW|qv8sr~BS0TJ5;##`!}bbT(XXS_HTV`3_g!FRdTNg=8GZVQ(d;OM22 zijL3*LjBTi*qS8%!4Ss7)|HOzM0(;NSy#tx{YZ@SWPMj-=g!8J81a?m?v{uV=SO}K zx?@$2T<~U*x*YEfYMD^v$n_p1cUgd2hBT0#@ioXm?48An**+&R4hH9o-UGpzS6#1? zN58uzv&w zSvwkF^4?nB*eViT;SxsVW#o)dBCIP|Jt{!dawSI3sdwcKRIgHB8XT|#0#dh>stE_^ z${JpN(#lk$WE4YgXji`;-5b3PTCYaF94n~7UpYgipTA^5nYNFb8Ni2g@}8yEE>oup zHNGuh<=1re>3}|Ul$EiYj_KTIW!PbSj)&3Wc3;8QX`3_NiSI7b&wcec>ss&Z68@|j z`M!0Qt5`MPFLQN>?4Gu*dB*(PoZ00KV^%c8I6`1gNUyV<_U8aY=2SY82?D7F<% z#u%S2&DTWR%B2ybC3w5B;fGXy8ra*%Oo)E$ZvCRhjDi)(U-6oew&|ByQ(16}wWY8! z{+U-BpIuo^8D(0xK6RHM^4gkw$VnE5I?46Zk#J8R)lZ6WePRfOY~pJkk|Lf9L))(Y z+V^6<@%Ku<$g)1Ja{Erso1rQ_n0h!3gv;?Pqg!Sx*G zzj^ykw5e`XO356E@i~lHnA|Dm`IkepZ?CHK!1Q##qDmF1<<+KE!s~h4CEa1U+~e@b z@S~`|ecq*7h8`mGM4mN%tuMDu%x+8Ng{R&R7Ph?mN$9buw3plGh=++CV{+_(JCda; zj}W;b^Km$m^XEFdjamn*wgA-f2W@g&@R#amZy`e60 zRYMnFrhV+VxuBIwbqnW`$JdL?zry9d;`+4tG-@K5*`aDAtE3U-I`ab&ncw4U?gzkj ziE6MD?YP|qqrrw~YmHEJ-j;fKf9?RRaLb}eQXdu3ndco;9<3|;##$k6p#+R>%}0hd zg=tqyyiDA7>&(;Lv`d2Rb zjd4tqIvTV3j?Pc?6HWEqRfdR|J)6csk3NUa@Ts;+)oLYXCg(HmSzCq6kq1R0cW~#Q zBuN(m)6umLSU_jhbP~+iCNu|@FdZ7NyvrW64eCAZs@V3t*d4vFP`JME9HU8&X3tW6 zDRQ~)ajxo&QFS_#t`z(Cn86p(9a8Vqdw?gep`-_IX|vIxriSH#};B(@To0zkmXpH6n-1^c{=k$4{Odsnadr zDCN3ne=*+H4*D*(_dAF8g`tgYhR1r2Y&W{Nhy5~5pmqHPlE)#cyHBCBs+-Boo}Ps( zusA8n5Tgf+312jJk0*0fE}h+B_<(!zX?UQ!LuHT08fr1~LC?uRoWC9fd z_;`rI_JgO=0~UsUkkg$8##IBPBpC_j3Pke;pd~uo_i5R?+;6o~qGlcCEZddk67G|j zFkoM3t^4I`nsGa39?67Z-1qkItE`(FT*=rnXl+jM7MebZI+Gh(IyCm==qg@wBJ-5l zBco!yDtp;#?z-MB^Fc=^?RGw>^~}h$gxifx|DF>YFm&uvZ8|zNmodo62hgOzLIsg# z?nelBcioKW7I9hNbI)^ONc2aISC34Tw%nslo?3}P3L*3_rk`dT2)VZ<6uZSkH`^L7 zIRv0r;+=hV6@N&H^#8n|G7j12SDV z`v}iPH7t!X1&0&PT`YKQQjGS}e6`qv{!~GzC1A`pxjx~aM6J?Gr_L$fuhR|SpLZ}C z96c^X&|Ey;6JSyYtwfO5wp}q_E5xGflt#2Z?&-C@taW_^Zb8Jy@F?LoSDM2;zrVqv zW{d!W0U)OTO0d-pYQn%<$lb&__->hWuA=9Nfs0Q|6)VOmT99nb3bQsSLGSieaQ9vo zBiB&A5M~F=Ss8#F%n_>8%qn`;s%(KfgS&i8Y0u^pu7w3U(wL}T$lv-UR#1ge4msDI z=G-V5RylFQ^+Z8M<>Am`v(t~20|A;EX=qvX5rv@wZSzM_%!VptXsc1!DAkJN}e#9b8#i4DpI^9fFAI7aewD}&O;E^J?eh8yw zRD9dtMlnaQ>dt^Jax$MmV2aCy@E*yW3u$hB_G!V~2~7Wy*uI!1P%bN)US*&N>Amy& z8pO3L=XCr^^7MdNZx;lpqKAeeeF<51)-$~|*{L<&kU?X~1@*$6X1X}3?tSwqY+KZ9 z(8CZ2rkT_QAUatkQ;MS_2>e*CYw8y~ZI8Em;I1CO-w}MWk-rZ(s9&d)-*%O{V;I&bBRug53}=j}E>(Xekr&6w3S{>n-_hk=;j zoX_ldMA~)wxp`cl+-=UZ%YEJJ{qJ?R;9S zGHf4SzJYY0+{NYT+cGg-tn#31A3Iogd5w4+#6Z2_|oD2s-#-%uN~Rm5S5(2=#8w zy9p+v9IBQt+TAx5g7LeZ#g2wGk7|u;-kC{>tz-)R=E3HP9NFe)x(=)Xa%I5lYgyj# zMM#6|MQ*K(T*Cm1;;pOp0~Hoh-?KDK}wjV$1uH~DhaxpzUp zRbm<^7cHH8BB--4;FXET`+$tCWEu2O*#!@?3!;y1p7(^<_!MOIT=su8&tOaUO0xOA zzf(Yh!J6Gb;thRSHS&e}PT2fhMu1J5=-wOZYhxgiFaTRdWtt&?0B<|59p2x*`!K>j z*3zvnLO%v@?vHdAlva;hHww{eb>y_l$F&%FuHyIz5BNl~f-MENH?~ouqkbD``5qOC zxXNMA)E8f4cfZY~e9QNohvyF|jLgQN&lGJ9bTbR05gai$9K1tTx-L0p6UgV2BeSeK zHG6Em3%#eTKF4o$s-Nuc7%gRhXlx#dcQhV6G8QASWGE6RRktk)8C-J^cj$*zo^`6$ zB44v8G@5=3WH~-k+K3(wS084i&GKqd(K%uHhKwqmvtsUlf19UO6w$5zDwa%GNFK(# zjV-yXEOELCVpfo}G?Lxx>aRbVOe1)Tt_<UgvUo4u9@xfUaQ#T{jQRQ$75K3okPe{Eyzlp;yG5;FU#iaBnv(hm> zDLy7sASOCuTL~Cn{J_{2{Sfa@GFRw_pbTg+Pgi!8@d?WkHx1S=nxdFoR^NhiQir$r>5~cGh5FS*8h0g2tq<@NfY8kdxMae?5 zvliUF-{nuZt*6vOi&2BdBR%Ca1qdPg9O$gqv!!XHjA~Q-wNWO!&rRR;3I-IRsG1G= z!Yw1|tN##>@^vHSBiJ73v3nYG*kcqC&U|-0M2AdZR%AlvSMCj{` z4a*3Gq~V_I<^082I0lKMRG>>7AO1sX!TJ<7vGM-o17{H=y-Q@gZLV+C`|3_~vb;{q zRaas&xZ6Iys&!{4cyOwWyCteM*94*W_2z&%$3M>#u$@sV@7>+gT`fGT_8d&BAT@oG zH4*s|>(fSkuLa#)w*YUCo72bA@G3eeMLKkNOf>1=ga&~XJDnXVHhH;Yj@Ws_RN*AS z`OJZ~kZTMzkUq7Y=YuJB{{kdSt(edCmT-3?-g7NJ{)b4k79(a|gG64UDI9I{Oc9(0 zkmHeJ+`2vj#4iDdK}111F8NhQNxkhq##-ku1c7Ur%ubyFOAjptJBeGM2mD1C5>?*k zH`^w(?@?=`X^yJyX4 z-nu6?*e6ZD3Z^d6thIkaS+`-U zR}LjjbtFo5sx8G+K(n*%I9#L}Tqe4WdCrz$?5>mBrO4%tt{!bzH`>y|UmMV~fcN#<30dy_!9NEpJ2)ksZV`D&8Q&71!a?vJ2>S)-hj zBC>`d%~7pi7!cV<>O>e*|7RTvO|Kj7EQQs?XqM#4i(m3fVP^gZ;ZCWFCOfkTiS&6G zmW;QWE33SjT1fQPDtRaH@3qJOw|pB6j)y|nc6m|(BmhgN7c=W>Dq z4VuajXKfE7`cHTKma{drA98y#@>?3pkFd!9yF{9Ohuxu)P7nwq0i?V9HfZ1{v{}&! zKw&!!MFJUP``*k0$ddu|^Qh6@2#}Qji>gceX$NYIJLA0{gMO%UI-;%2|51rb|KU*f zHyXyBY- zN*2AyL1J^HqVJxHmX^{OV%bXrQLgVu_f0y@!QXtWr1aJ$2X2K<)X9dQ#=Q3LLFdbO zo(D?9ha5|e4bSXn^YNo2t;x%Mh({7*t42$N$3@AN0k%u{cfS(fZzjMo$Qa0?XumH4 zB$su^FL=+?^0xg-U)!bTlOJOF=gWD}D?kQW(tmgTzZp&PEQmrIBgji<%EezV)?g0N zP$ok}8xFes>D7_lQ=TKNXtS4punp^aF!*Fz^N03;54&#tZLI4iKN1?Rsv;9?O1frT&0x_S2!;qWg_XO8u-v!)JWyVmt3Peozbc zqY+?nYSWFi{~}XYFn+cMB&TvX2LBCZK}am(>fbPS2+>b^_&4Gm1LDFxeeo>?{AB&Okcm%cp;v#D3}r^WRu#KLX43HGOE0rvfG4F9Gj{M*tH<%E1xEeoZ&}o@G!vl+rN{iWZ zRgdPESDjWyPL9N9OQfVu?Bz#m)qdKR0`BBJJ0TKSBd`8E6ep#iWeYCTEzcB|a%Xf8qS?>gJFO>$n zzb^g57$n}Q$HCgWL%(v+M{4Q2-sE{Yx$MgLHt1M`x=Bl^>tLc?$wD=Ls}V>UjzKcA z`8gGl-P~`^`SSFB9yZXM-4Z^!h|67e3&sdWo`1fJNGY8FxJ2oM*atl zN6f`@>7gK_Rg)7uG;M{ z_zn`qo*$2~jcK48zCK|$C$C@fz8?L7cS))c(nR8Py)O@t+b~a(aB^liCy4a+wqkddC0vl>NG}X3FQ!DHhrFYD zswLvm$bxrZ#&q38!PT1WDRO*tBX8Q!=(Al=`Am?3?IFicA2NuSnl}JL^GB^d=7AlmbLi7 z!6GDZ+4$Tfmta+bInKL{#qe^ZURaXOJFy)+*5r#Kue!Mg{k6;adR4GY@1aRYoonCn zwB!({lH&7owt>@iXKwVZ)^W%9K?ve7COXG+HJ$}1m0`}f&*0VrSo~C9cGDsVuiJEP z_*fOnVbF>M+#OK$` z^)<9cm0+qPb73XT{kzT0tLF#qglT6Z($FzEcH08&;n$sC-*$#dCEs=QRYVtt%f=db z<$P#Y1s7evz?N;fd2z=#)^q7PKBYVPiFYh;BUrIvUmhMGM%+wja{GW+{^ULhodt%3 z-IW3bM*YBw`A2BJr+6@bw0D;MKxhn|DJ|#_=RWZd3oS}{eRlp{|1jj%BMhs|C>Q9L zmVLUa{bC`m(zlXcf5dgAb(|>(Al1jl|DF2ef1#(~ioEYd=TVErlIirIq67MQ*i|ww z33g*QEx~&7XLiwO`k(_O=X^WW0hs`U5$n)@?On z=ce-!7kdHvQ#2Im4+lWGitOC#Vs z8_-TgG{e!SHADBX84PCilU<0??a1Ah=q zMEusJm^bT}shKmjI)vFy>mV>txB`LDB=2zQ(-A@UIY4ZK4AeWMMtvJv82frvSXxEL zPTMz;3(`8$zEM)aBH)^~KP zZ!0aH4%KdDA+>d2vR5##k=Z#q@rkwCgvZjb`y99W4`NR&&;lOp2O<qj#r z?8JomJDiFJ(2Ga(Ra3$}hzlPzQ|D!&pJznpA3ytb-E>e#Yej0A+r>rG2M#f_(m-y~ z>$ZDze-vMt8qtPkjz-b1I$8>QtxAR&F5M06+}5`t+dMquA;MYNu-^nb0uf-=xoxk_Ffs9Uw851Sgf0$jZw zg__L>w@P~k4MnuaUa;z|pPJM3o`L4XG$;&h_FlYpHeR1~RV>I`8Nkky^#hn=@Z#8! zlB;VMIdA64_m24C;+c|OOma`DjIdn-Pu^%%D*#I2II}=vu-u#eXDz(nX!1Du*mi`?J9j z1fDR}$UU(wfT76v`>MXBQta_?;L?D32A05QOJr_~GQQ z2V36;w`YZDZp->|!%akK-TS<03p+lkN15K)sG3z)y+V801XZ2~Q870?c8|Byo~;U$l+_GGOrQ0{xD{(}l=8H_l|W7iMrjpaQ$M z>gH|v^RaJ0xwbSEcr77w-ZQysXJd^yBzcf!%;`B1GCcv9B62f~xPO6l$xz0bm0PE3 z*Cj!#lZu!Dlqjp`fy)+vR07;Nt;49S1C6}Kn9-^B-e+C9c{Ri5#h;KAA98lUnT|pn zWW^XSfa8(kotA&%lI}}9DzaA*<(nl=&<2S8CoAHDwb<8Q`8$8G=wa7!xIQU%q5Z_C z7~-TLzzT7PIW87*oqWYrAf8q_G5u%vqVgFsD%GCe{+~??Y50mE?-Y`C)k{Kf{@m=b>)XU(z zwFsm*N6PS@uxTBF#oJrEImIXTe^9T8=!53!+kq)4WDrfT!e{l{#uxH^MUPc%?d7t& z+l}wu`$OsJAHrl5Olc+ys&d?a@1gL%3b0MbSUW#&0(LVWl(2c*V6L~e3jeM%QlSDW zVV2PRCp)5{N0p~pD z!s%DH?2?6tf(L!w>s-?P#3}jJnNc=>zT83Ydsu>aVADHyr?pJq@{f>&H&MKA?^8sFEu zz?YgsDnpyA$k>Ou-*yU78%ffX)t@V+2 zc`E@kodOapp!Z7#=%DiZoA3=&nT;cu?de4w1jyp640U5k^ERoG2~eBICq7;$0o9;} z$C`t@zcCv^xH1!I5Y5qyf4TsTowR-KHS~#sLSPi}9AynWNHD-iTN?`q0n&^E}GI^23@7 z-1K9IGmzLBG+?Rm3VCI4(clfyp)qpPT zEh7qq?yJDhCHyoBDO=~MLPD?N?z6W;O*nvLbS0ynVYSa{`VrH$_Gw~|l&Cm`Dj_-6 zrGgGqucNF9H*q(Ve`4{c4M$wHAc;EVkf*X3F>|F_(q2FPnLGk>XxF|I~qmzUe_$#IMcdS*9{#ChK9o^2~G}0Z!Owkl&W(3KWvz zZ0^Nl7ibEAq_0k(HcJ+cOre2!jY!Ieh0gmHFgytdcI_t>E{JLvlzEG z4YjQjJRVgX#w2f*4~+4Y>iezoMO1aLygTz33K$)Q=h_ViF=CFpxL@mcbg}J6SL#0< zx9N)=w5pPM9=?MWDa^I5x~KtEe$ty;6H0mpb_DjfpZf;$J_|C^6f&3TT|G!_VYzvi zK}z8gB5=o}C5ut3bm@#^Wi2bls|w?wTApPv;WBau(iHWS^j8kNbO_UDIC_C9G-TQB zHezX_i9D2|*&+w^_#f=Oc|6qZ|1U0Sku0SWqTCflaU)BX+@+HJE}<;rE=jhTEMo=@ zsVEhSB*sz+Nlccp%~;BoJ?k(Vk#)w5B{LYy@3OUgKA-RTW(vG3H$L0>tH~jY0zAni)p3ZN zD8IxY1j^ar&sT?&)GyE=~X`ZAgl^d0t_nV(E1T;z;x23)7}%9gGjwyEs;Yj+Cjv5gMw zn{h0kKgvbF1$gQa-rY=+j<_g@U0@bPSeg?ZZ~qy{o|X!;x?;Mz;z-|~qh1gvTau+{K}ko?uo^s*&xGw9D$vT zQMoix;#d9d=BYiPmd4sB>18B?Ava@ulx7S)JQOZb=NUs!lVI32?~)cn6Rr(-J4rL> ze6xyU*Oh$YycwHSg^~7M`{O>>KV&)&n7MrThGK`Af4!&f9HhM}$lk8Ne00^37n(s0 z$#>F&EL7Us*-Jw6erKq`UO((U-Y70FnPP@K&@fX4Rzi%1X=Gk|$$L*V!gOUYd4qQM;`sQ2S z4~iVV{*WZ;oKbXm%v){HSN#J2u1-yJw+5Or5jRe{YVUnyP1#I3%~Wgh41$#_oFHD~ z$W*hS;>^>w*w)E>%x;+nvBxaaBvPMTv%NUdVnjM~{_?l$kcqb!Y*WcYJ(oBVOM&O( ze_OpQ>rU%8`eYvoD(?O1cj?JFnpXTQ6Lagy*~cvCTwd6u#61v`Ecug)to1MwP0ECW zke7S<2E{~x0*VM_NMbWJw7bK-BYx&J*7@(06c*b~4DoMU z+SHNj1@JnH6a6%TU4XUfc%M{xsek;OZ~O#peA#*+`^IELQc}|5XJXKc_N4Cyb@D_l zkMO!qN<~;t)XCCh@p+PAHxfHo!kHpG~o%+`N2nCnRC)A`JcZ zRknOl*yvoFjGid$!SV`a28>=2<8#Pa zDZUVK;VwSNCkdBNgP%C<0LyW6tmYLg#Jjxal#HB!ONOjY|1LjX=WJ=6K%HGuw@B$X z!hJva#Rm%oxPXc!&yY&kjNg8VbSyGHBTeF7I^}P&jW;2z`W3te96Qmd>iwN$NKc(s zlzze8_!I+rMcU(_Cu%Nq%^E(rn3+)$KZ7g~!jCT`ozeQ7JMi=>Q=?)3QZP2QQ5?A_ zmP6Q^O_<0p4G1q;IE)D3RLum zrN&YW%NUYQz^$1H^RsEO#}{V$X^DJ#JX*_cY8X@|RLPdsced6J+kfcVhg0s_lXqwl zVw*&-O)x1B*7M@;HoPr{Mi?%lD~e-06nzV{6ied$nhte9gKMTOLUOZ01s<))#r)fIvlrpN?K>r-+SS4pE35F3~-k12`Nz<>>DIw)Lfpa)NVLBVr_y zXG!5Yn(fi%dO*so+x5v&;7HdhO;G&Gg&k3PD>~j!TCWrqLMR}~` zLdJ&@0xv!&@2+DyY(1vgYaaO^7WJ{Aj0i4R%jsoKWf`WIdld!c2j<_jmy!il(Oy2J z;_>b^vn^G{b>9V+Vs~y>K_Fpz(2-L;lbCXOVY=_&4N7pqa7po$-gmZOK&(9QtT)0`nrb(6JIN|mfMjNhXXvM7>Pq9A;;}x(`E%VPqFIc1tsI1^9v+9 zC7!7!mm4JQHEl@cysL*_SrBKi#yUJ=scrG01bCWiO|GFQ8Vag5RK>rm5B(aYAC;+W z8;uBL4~)`x9-VkcU_HL(@z|z0#!n&;5!tnFP_Ktyb!>sgQm%#6?e&i?O<(+8hgmGx z|Ng-9ntkRoh8)xb&fq4|JF^_haUQbWP{88+Ue2=y=Te}_hk5^&oSm&+x8jRs#%cvD zL`}Zb_;=uPjuqq_Zfi(3gkC6oT~S^}YqV5NY0u5aMD6wyK{BcG&(qWUUU3d+bvGdo)L(iJ^rv{VP{Qd)!w9`=+bXHcmmGa`OnWXnFuM9 zg)w=b(S=z)`HJ~%XG;CygYC1j%D`yiP&9?fFNvF$V;&7yPiSOCg3}S_$ngu;-H&(b z5mm(!UAFs)k&)*#)!dX)NY~F*TesR&`Q$Mivi#O_dV1ueIu5jIhMJP`@md|96YLS6 zy5ERnD5?#;FIF}}P@inC{~Ya6Or51)4+1rHYTYbO}yP!hj*H^J>Th-EVG?9J+Wb&ueieHaDFa)`Ldh>}PKnlj3Fu2NJGR(dJ*} z&yQ5=_)`xv{bk2$6)6sWlV4ogM^;0tICK*s*_K=3rV&6^)??;AX6~-4X4PEaTwVw? zlIK()#9BU}*TSllCU%53FTPB18&XXWPpHR%5RNz@`0Xsz1%P%-r%QXCZc;9IYawjd zz0*&nZbZqhd`7gfB)JAZ4nl0s4mQdt1EMh2tHpxU^~L1+M|!JS30=xus*-&IB8a-` z(1KSh@5(3X=F9R&OTq*>pIvQFg7?aF>papaUFi0YGg0S+mEZQhk z9#vQf<-dPyZZe5BV;X&D!3)Lkm`qJ9vF}KP4=^1bpun~HL9b!7&WMatJ_4N(B*nkl z>`9ksHJ@pEBHtf09lM2jGx`@!5 zTP~#5h?s@N*~zBT*hHNYgM^N1;aG*$@DS8QXZ|>d5BAPHnuF<_T_ozXEwWN6 z<{SXBfW?GBtpm`{*yVQ3-K<88hs-QHQE_;o$f}6bG||hv`8A}JqSEgFtYGo3jc4yH ztsKUh{iLIRvgEU5Ph#oZ0=*+{#!vKW_h!7XFmh_Teb2E#wcby{fBm^EzvLhoH?v8p zuRGxRGZvAj7n|loe)-2tXGWm2sM; z$AYDx(T04B?g87r;>ujACl;>zZ`;jA1cWANhp~T5-ImrusjoMVcIi7%xZp3V=C~dc zqXhYW;%iUKr)6>H`Pxdp?@ts04t@LlT|9-J>~!xpy>oxm36oo99Oh}^}I$#mBq34|B%J&hY?MmikHL`~}Y zexIo_l(CsXt;6318e&N6&6lz{EODmU%Oo&>{POwUE zao?El<}6UwF{DL5V{~u2fo&&9vU|u!xg&K)p=`nRuvXd$L*qXrS&Yiq=ZpOh%lPQd z1clI|=Gi8wao`4s-u97jorSq-rgZqcih~kpm$-wIq+g&zEF~`<&{>RK_*18=(&0f!gbpoav63){e@#3Pdq}cah*=pnO?gx zb=yYP>&z>8lctDax1aOOwU(-GUL1BF=kr5q-|GYgM=L-j%)x=PF8;))e1-DgLe6@V zQ&?$=Y*32GPi>Z9k+A2vw`j>2yQ%N8 z=r?mlhfcGCDsQ+as8cIzv5vI0TzG%Bd;yv6`y!Q}%yURE4-X|?oKDS48wAtN?+bBn-!nV;W>)p#{smD~VG8N+*g|&4 z@dAPK>6cTyQfP~F8VNz8@?#M1X!O;&g}x@c%+j4&bunt!mrdvCQV6eg?s3#DaZ@=a zs72^Zp9FcGd41+T>3#}J$PEv*FeO8i(nrXA7M2;vmJu!E^j9C6?Z00dpr&^4?ff5u zU+4P_zvDs+%z9MJAcFW=rO~W8CCO}7U+3u>eEMjk*6EDvU6Z@e59j^Cc&FQs~=X8N7wL5HO7P9CjD^Z50u{ENo8e@A{ z0+1P}6TvBTGI8%huA>ZRGFs>0i}}gwy*gB?XCT8@HFz&n;M1(nEmopVN_mg}v=5dN zbN_9-rvK~|4bxhAFJO8+oc32(nwU~7JHK>sme!OyXbWoU3oQ*JPlLt*j|X9K9XI9V z#xJrx{Jt=5sOo>pDmi|m!8Qu1-j0>|ZA2*l2WU83h7&M=iQ6;@x0vIoHwrUUv!MXlQYqfnm_rX6GP$Re8_v)jKouI>s!NUujbe0d8hD6=k7$%~a&ZLV9q zi_7pVL=(TKN9mUlch8c0(HN4yg ze{GCZFgY3~NZf&%<)V0h=3SYqX>ZgB$9id*v6d-WkwwKn}WkX2M0F1e(FD~R+DEn`Te zf8up-8_`-?y492iepUJuO^YDm-nZ>OOKxK|&4FCA62$v0G8O03Czl-WY8GXzQN@ii zEIGT1k5w-LoU4QTtykR@%u;d*vvj1s2>RF71xJ^0VIMlch2wqfcP+WlmHf++pfmoCjCF`{Udq>l>Tq*JaoRAHrWYq zv^8^F$r&w4`6$(%d1GVI>3_RmtFMFMWmUqr?IQ~6^&)>Uj>ENbo)Q36z7&xQCkr|J_z-Ogp*9n;FE%) zfA98cqJpuR%b*xCqp0h@_##!o_(+K5;r1|ggK-URoZ3I_WxLs(1YqZ1wbu{j)N4dL zl2BR-wzDj7`uk;!59UjbRgOy9cJ*1)Z68_lQ0;?$|FNdO(>vM=ThUhQQQL=_|NehJ ze?cQ#s43kL9o@ zLVj8;3w) z-m2Qm{KfQEquyoH1Ha7zbzOh8yruKUn&p95929ivnOZTMfBE76pwq`?9G*2(T{&f} zc#80nW3&B7((6W+b1GIQY>-oF#4Gas;%v4f^C$LV`n{MPFj~EM&XS8>R?-KQPt-uV z`FfxhzGpMSIxD27S zoBF2pB2CaSqbk~gqG?8^Fk8%BK8#`OD^goy!sSj`ELVKQ~j|`SmcpGvqAQVYj^7pMX#o@g`QR*~rh= zUb#3P?CQn@eHW`3r>l~#{g>Ho=yP*vVn;H%Cx|-d)R>NmWr?=Q77D!_7r58YeTlCe zk_0L;Xz*r)ZiT&dBhs(E)V(h3Di&J4yS{-ump-~!wV0m24m{8E;=0-fYTlFhD!ArG zY9m>7vc4W|9_m-Gl_=Pk-c}%@9vRS=sT!FqEm{rAtI0=MkfiwCk1}J`z|Ek^aM^l} z(^08{z2y^#wtw8`x$61GH345>Df9Ip`AXC2D*qc~H{J+rC??7$H~PIFsBEbX@I42N z#w4-B#E){64!FD5-xytE*o#9+5JHxOmekYs6CHJQ+R#Law?N@F!o^b=6oPe)%{Oh3 z@Jy&t_Az%zux#0^-ySa!s(8cp=!im~2r^8lRC#s#1j|qUOtSID8(6vZLax3$(AM#$ zm33llM7EG@;oS{AsHjpJkLH00pVCAp8|tUsjd!?qUG3Zha5p=Pj*+;3>V>-X8z(E$ zW^&y+FM||wrIYEP4sBzKp_%wYN?mqEUVDk?$sVZpsX4ce1MCNoy!4ly`x$ z5r@TZHe3s;Z)=bPFIR}(u<1Hq7F{M+t|04V5zu8jr>%17(r^9sDqq2j&MMy5xJ!Qy zHw7i4G#)ZQjaBTPzq~2=8XFR-QG(=mjRT@ zFa8}V@(D<>Coo>Pz9aVp*|7V}4@>e;E2_HM1Qs(W*TzZO`14wyhiuh0s~082Sq>L@ zb+I*FKIHmy4FpZc19sbTLif`L%YwVbS0m5%bxLA74tU$Ve@Onk{%AEiS&$pXfIzxO zt-*s^5-2&0fm;DQ++w>ypG%K%HxD%>A9F#;(N8tkiY1{&P{fDCMY@XZCWDu(Wb_Jm zHosojjtrFH{i%sTR}`}J-kUSXTVrMp%an&6wAhu#kB!k(`9vy{tB!$t6EG4FZYty4 z-|8y#-K6M?Y>&}D?B_M96n$$>eXMppRw6CkK$C81vhV4zVNcXwHgE%~X^K83+Ai|s z=W;gTUp2o{SIk-Mnrd|Gv4W&(tI4;x{*96^TuGoViLs7Eo_9VBt|5rQLEN<;XXRzd zT)L@Oy|dY-Cn_fSyjf?y{C-4wrh*?*6D2BWvsBGv{>M|_ z=K$!NuSJJDCBGZzxngWy@aR=d#z)&-M^yyjX>k@(*t;TRox7aWf>Mv0$|m*+3S=$e zM!Ez26no*?1bX^|FaM=su0)_}(iN(G;F?KUNggl0cx28| z+0aDr{p8p3gm=yi(QvT}zSQ;q1QomzSZmHL_?Xt^xC0^8b*AUn?-P>p&j$}82?PTW z;t{ymeEVq7G-b=`w+c&~qP!iw2)VUBmiR}V7anwH2$3G&1zaW0AAqa$kKzCPMyiv8 z0>Myztbzi_Op7e_9P^`RkgENk@rglzf}}R9!Lzx(oa@A{U)FOoK2Z>_7$`CgmGXD| zu|{Qv|J$t5zeo#Xdaqd3cwitx3n?3uICnPETN!ZzGt(mxnLCxSj?45HA-VW;KAJp{ zzzIv%u>Ib7s1Wjk9nd<$a^G28Ub4^fjHV`ugm6W}e7_8Wr)IdOw~XUa7`rSDuH5Kr}jKqVj77_V&`ARu% z@By>+T+~x@Q1F7%o~=ON2rVB(Xt#W2+kFyu6^9)}%L@CX19yL~;mD|8P1=A(^zex= zgA5JftM~JnSCyf!CJoTy9@PVsbHhc)4qqCGa#11Y%Mn87KGzzsjoZFkMWM7eQcVc9 zsa~SdMdz;awu}T6r3|KgWK^>|xNesUm0C;XiEaYiJ{I;E{UEgGJs)1WEcS`UiybbK z^m==CVE&WOVun2u^z>`rF%m{X-3dWo#gJ}8#=ewV{)4(f_O|H!-CojPeF_53SPyB4 zvD<53l1;pOh=@p#rdx<*XX$;2DHE@g{CaKVukjm3;0^aB#{{f-;;cal7nf6m{^^q! zS1j8~jI~iMvupz-TBX(H7G4k!ee+%^+`Pyz;>|IIAupW@LFySL=<(3Y=dRs%ztWwd zgo*rE6hhM0EctZa``%3_>7n{`IS#bTL6A9p!oH`0PJVcJBqg8oLdSYN*TV0M98KK_ zDLfo_!FW9nV?7L$T0L?2wZVeQqE|Qm5f9Z6ng`yIyaZKrAmREtb4^;0d6wU7cWA6F z`2%ch`XyEb%E2+B1-p1gr*ycA-TwPZ_U}Ye0$rN{H=VS{=0&wL?!H=9s-#P;k&a}! z-2KQij4%uDKXv{3nP64uR_miJ$2udrERDSHQoC>|Gdrje(++I zgU7Sjn%sem9Q-k+i`bQJgB&9EI1aD zX?}&{`^Hp@>!n*Yay+5WY+wa=$y|#aEYu1guJxaX3+Dknqs$w~eT~d0ERyg+*U@;6 zPS0}8nD5$wQhY3^V(!MB8d0MW`IoTT$@cV%!QY>sNvL}xQY+on0eSp~$*3p8L`J7i z36t*aJH*_xRAm?ILNoPOFPF*2f&++cbfPT!nVBwCII*Tf$ODr-V{biaKW^ zSo6rwRE)mFPJ}Qb8Q(Xsu=4 zN=@l{Q*`lqtk+h24E{@yW8u>n%M|bH6vVOdVL+1p`={)*_R}jh!l^tEKO?JDzDb+z zvu-HP7xkw+koYRM%v9UF0sm&N;&|1kGnLR;lfjxVv?Ito`9fe&GxVazqu`3 zhWDnU)&gf`z#+*7mszYk{~;M%lBf^;NG{eoW^y1fUp4<-og}HPQK~(er0-g-bB?s7 ztAS)Otln}`dhGo=AUcBwc1z*hQj$PRW-O%{9OtYE-d>p@g-)>+1BG?EeW!~ zF-}F}{#Wm08Rr?tq`Xset4n3I6OE#GF%z2UT`FUTI?BJyLB9yhUruZqYQGimD?-o< zE|qV2SBR7A6M235Y)^;ro2rJwq7z;|4Ju=@nn5Huy3;yjtL@vUh&)t|xCN>tG`;;c zU_qiDGBNGVKXFVgm>}$!K$TlAM@`b%_QfGh8yPRb%V0Axj(AhdGg!M3l1x*7nCxZ% z>I(RTQ*B>ugajf&JMQ28@>hWFsCb?H+BAtfG$C3UZN)w}9)R+o=cQzBJc#`^@ajhF zGr9WSF*t%YIk>XWzyO438rrXh1mi{P(4tH4(OQA`R`q@@rmvq>_AE7z9aUhs! zei&R@*>~(q_urhV>{UXurXXxb6jtK#p&9IOzeV@s{Rr@^;NI=w>tUAXZg^K0^RwU~ z^`;kcx8A&|#?lr9B*(~w3(LUE5!^DKH2$p2+9U=$+;YVzS3f39^D25ci>9me`Bm1U zUZ3ferV>)2qj6EFX5m|_tBEElv~+B1C4u#B-M=>!m;SgteUI_;*)a1??8a_(iR0Pd zr!LI0>INmYd8nRJzfA&^A*EXCcq&VcCGfrqTnHwrJ-1!H4$vt_m#BfNTb*KM)gM zmvL=w(WE8e%|>MPzkid^vQ%y~*Z&K+%xxpEDQz8f+&Qs2h9mw1$a8=4f$iQidV%oa zSQNM(X4LY%a1h(UDrymX?uS)M{B>|2d8nk|orv(~MZ~O)@8PQB&JHI$19X3Y{Ru)y zIhFZii-LvO`vqcOD^yo+kJ1B=K%$y!l=VAOg+TaKPoX)pTh=_9R} z{|=H0YJ_4L4g!^w-PB_Qr_}F4HMjT{>xw|}hOd(@HR(|^_4E8cAU~u>PebopxT0EC zmj$%leTTV6X=K*s`Tm$w2&F&r!$Gx5sKEUENf!^&S<0bSw;fmw5@w@hr7w2puHVE9 z+KIZt3#jkZ(-y);3gMSCECv>dWan=&Hc(sBqJ2%VDOpBmf)RK z>G|YkQ2vtlGKAh+6KL7^6g`p+f0|2>$DciKbI9%OA@`;i`L0uk3Qvf4x$|EapyUVU zD+zkbYt#Ho#e|S*!wSnt^_mr#3gG24shc2$QM3}HTJW6HkQO$AmNPKk+3=NAM!IqQ z)=|hSAV4=Eu_4%7lzrFAzLClUi9BU5Vs!sp)qwQV#-zF@!Jh@L+~~h`b-NR7JcgB> z$YNdAEIWCYD?k|8e_k^zT8cmLcl$L3#Lb(=HrS7CJT23sCtaTMkV`_Z9@KH+&1c2f zq&VfgEA+7l_e5$2Te9{bG!T6#ac-E^Dxjek}0Nj|b@k*==xuE~-#U*lKpny{*ZG>?-17|hJ*uDc?U1Sp_ z@&+19U7C#ZEWvZN=e$ZVkswbFO5>47qOzER~ z|3`09rgkeenRjn+B^947BE@`zEZI{1# zC~rzv5@~A=96Ttg#+z@HF2AsF8MR+uSWUAZVSA5)7xM6wWEMAz+^ioY4XOw6NXZET=w3vR0W1~P#81b)0z?Dcnq zA}a3a{WHsH)8vg(NNiKzvXNrMk)x&VX()`N4`eBi9bQgN2gT#)gY756mj_mi>ro8}U3t@|b}rJz{PW%dtI5C8 zyj1BFGr{HL_|gRf$mpc{k_#i%ZK9q!+g(+gq0s-Dk!CRfarTYwstzVDv_4)B*Yvbb zfl~hZ$H(JE)mUv`VF&7JVvc1zfl8<&3oc#rTDlKjmxU(|x(_S_cjiY6;tS;uU`FI0 z21B6HMa=Zfr8I}NYS%I^q}DWcU7#sN+_rukNT7t*9#F+( ztKkkLWZzV6#KjM6Cv|OF&iDel%p=-Fn)1b7zha_?@A3eb*MFDC^NkMnX%dkxi^f&u zoi^DL%&xy&0(RK!^uvFoT3(M)kl+P8zC|Z zFlJ~Vf^NIr)_a59df0xmG?P0}a@{@%+NVG5uqx?^X2Y3n$V7Gt*PfDNAZ!iq2M-&r z4Z`CUmgRx5XdFA=6B>I#;3934r!s@S&Mn#RT|77Dk1^=v+Rq4sp7EiUa+Awj7esB0 zN_K(i5&d@{LsMv}H1mpq>;9rGUqUel#-I}`zj4dj?uR9o{?ti!pqf~?8P0Dc9y~?$ z`A=KS>!>)F#1V=OkrcR%hbmK|z;z!i77ul*_~(znQR$WEjB>-i)XPYnF#(oM@pfnQ z>BeE9GsZCKJ&8@mTf)-EZGd0?*}xzlUOyXID`R{5SlkyO@8zH{D2JXoV%!t8zxiS2 zh=b9mO@2rh+f;q4I;UEtcr<#%SIZhU5W!+y9J4 zt5Ud-H8Cqv10NL=gS=fO16iQ!njKL)QM-|7vTbBWp-p0jNlLQ-z)q}10Rz#;j!OWj z=Bds2>zc2#A%k_^dMRmJ)BOGnZ&oRkP+ZM7Du^NbU<(~jy&U}57b7YNexY-fN$vrx z2lsOyrFOls_4J`O9>gl(>XVIc2{=(iRu!Hb6x*=LQ+_CWeAegH$XCr27%OwnFKuRV z{rs@Ay2g^D?|Q2?fEbI{YJ zrNlDZw5mRfW<+vImxqs1S z&_kyIPIO?|#NORwtmGk;*_qpgp~y4BnR6vv)M_9AE^drXCM3BAX~t4yq4u;(2V)B}8K>eNQgAieekM|Y@GsjH zTu>DTGyb+CM!EvddVk8NyH>Y0e*c2}v>V0lN1~aXh|$N*4iIQFyq5lUTzh*BCogRd zRLc`#)&mNAVe!lJ*E@2&pE<{!Mo48o%9N6?h3~1%zkAs%`U^dg+3%iV6YN6f?e#pW zkjI|i_?{su21#30fft^WGeygU(h#7$Qaq3(QTpCN((w0n`X0Pi`BKm#7`WZ?Si{fc zC!-q1x;cHQXjW2Yo!W??R3fxMvcy_2g*g zD>wF1s^6XoV_hK}+#JyXYhj$_5GE5`7~Z;8ZH;?%~TmIfxh(x*71QX|n2sLylD(&1Cyatv4;}my`c~0Xc#=`IApJ zmT88lh*;yv;zH!`*y#fb@LJp=YXc}b$8OnrUCI($e2Fgr?y5Hpx2OfQnYKWgs@ioeQv5Con=l17>pEM*?2*E_ zFmpz1f)n(Qcw9R>$mfX3WXUbhea}N+6FEhtHl4_=7S=;rQN^*U=}{hZa~JBzsuGIs z8Wkb_q5*&F=!LYH-RV@Dr+@ngka7J@+23EPa4X!7#!hUJODG*bn~7!*jxls`t6_`g zmu#GJGUhJPZ(fxEN%bu*6Gz>&QUbpqJQ*9{#AYr0~y`XcCZP zUjPP~fcgz?Snk{>VNi1sBh~Ifxyz|1-5SK-62E{cRG8qsCK4ix=Gqg${K(%REA$W1F}Ik2+gBu}&afmDgY zCw0d&Mx(ZDigX!uN{_4#%twHmGS5a4rHkXBjv)RaxL6?+$QDi};x>GD%UG(D?;|~S zHs-PZA+MdGy70QJ#5A8WN%Sr-lYwTXZN(>A4?(yUxX8W(PlB&a%;yZXEpj~K;C;}p zq_j=g@(mFzi54NpE^GwD!X9zXq077Ub=)c$N*LT!qPLF1?bpMU{zAw| zT7D53CoTu}{jv;4$z0ZGSid#p&S&Cx_~62yqBX(kk0Ra^il9mA%zPamqA`*3^(EFI zdgi-~L2=%>#1A~^;`V`MD%~G}Y9k!vlihMNstMdMxAia;){J}4(F^yr z@uXq}E>~Ji>Oo~|k-@JyGk26rZlFs@&!+4t9>j=dF-qIR_8rUe@$#KKABoktG6@?*!O1T(sOTQyV9|yg*)G zL$KtG86wm-Qu?XxYhhcG)E0L~M0?eM$%Ia1om-uxx9wx=q*}6jh(aX4MKVFG?E}&> z>kWk>uO)@cwXc~wwczTaAWtsHk?ptUcUJ#NgZ#li6uScE2=9(NiA(A_z*{{#@KOaq z`Q#~4@>kD>+ty9^+_BM0@+kD%NAkmd!Etlf>W1X=5itSTC%ymKWwof5ziBeU!KJH^ z6ehzLahpI~hmX=CzxNh+wNL)2>wTHCLFq;^;zJewQ12#lY!~n8rWGy=HH4$A2i-IS z-pU?65t?+mW^C_&rYhRXE6p4LmR&IQPhu4~d68+a;v2^y&x$SF5Bnj-b5PD^U3N~~ zH*M#mDcZt?fZ9!Kl+m%N{_~qR%sA7MxHqSuwCR1j-WIe|b>JR?;#TOr$(y2sbFQoW zJ7xt+#z4*Hq_GHksDJSzrK6B+>^9q8d!UB~N`=U_lXAurHi7c2Cq7*5fy+4ENRp1y zj;!S&HA3B=JrvF_e9CVoqnG4VgYgy|I9PHJDg<#9R6i{5r&xVI9eXx&<2JEpkJx?c z!E+NIIFx^K)-^2mo4@Zl#kinM(_f`3Qt6_{@vrqModrY2wQdw){VPzxewDGaPTKK^ zel6hj#{ze*$LvQxJ0RLZc8z>^I7OOqW8@?CNd2PHR<}>duO;Y3s7<4J*RmkVR(<(Oep0~Mvg-+d2CHF3M&FlqmD3nCSDd21^7Y?5 zuJZ_|wy3D$3o5wP8Kx;t^59FRWk2na)hTaY|HwVI%(a)-2e`Be>2Dfok8zBzpZaD z4#C942`i8GUpraZ-^QoZe>3J}x2al{?Tgl+CkMNYMXq#WOVJtXwN5YfQmgMy&1UVY zX^1pM4D1A~GQO)_mGYbMSMoq54sol|x|^QHUsGy}q(|soH5!Qd;40g~1&=2FzaPLB zH4=@Jb_I`j$;S)awH_zuoV*uY2UqPqhSfa*1mh%Z8_sj9NEvfTmu@XoC+`hz-{qh{ zM*T~sT`*3!Io99X)j1C1ZT{xZQ@R?ZA_PdFkGLb`JU9>j`P`NsSSEg*1JVSqBuckB zq|iua*PiD%UVYoak@MgE>dJ|))u@sdmBFyK?$Mxs|AEyYJ0LERV~@)2yG*N>aHyl0OvfH_+p&T3*C{%6s zqtR{1a@V~oT&mxl?KZBQ>zAR_)%m2OM1O$=RwaUAIsAhAtV+I^7#;Wvl(F1sUTz03 z)UGT&L;WX+341XLs+|Z7w_EJ_31Tic%ys{}vs~EfUJKB$g;l&ff}7_sdA-ZW`V|`Tvh3C0SX#UP#9Egpz_q94 zKMXUWYEVP`KeQn3i&a?v3;MS_0N0`RlCAeP&WbyCFQa*@Lbl{6{Q|TtProb}GFtc7 zFL3gTO8y_)=*Er`b^X{G90u5{%fDzx29aQ4;NZ09%s{uk%XSwhMk)oaF?sXgVpVIX zUkIoPK)Flc+T8ZLq9Kx4hux;iy$lbWC*Z8%9wruQwkA8pf{W?_v8O*lEet=0Dlp$q{j+csBrMP4f7j1^Cp#&eXVRf`huwE6-7bh> zgE2QFSCyyv1$a-4!y#Rr4OA(bxpUu5v$x(x1;#NVN}CXB^2!-4*iDm?^UB<+lfT;w zB?Xn%0l!rYScBL0l>AezU_&kZQiw9p?~$n1`j$l+bdh{^&jse(4iK8qh@n1HHJ4T~ zuCKnttXG4Rzo|XWm~)l)&1GU3sBPln0aYzd3`@0+?{K>~464{#v4>w?+w>vkOt=1m zvD@D!d_I4QGOru^#t_cCaP@4!|7I4@wvv|7w2V!Du&wxE2Oh?;s*}{?X>ig0qR28* z!C}yjesyw8xYpk_ZSI*I!=7Tv@7_IPT^fQv7M!EH`z3ey%vmZ`Q-)&8tdKx^8Q5 zRKIzbdD1fdRo&FVk7xUK+fq6Kz0i}?Iq=Rx*mpA)g zrIaG~E>zPawM?AQdV^fozdt4E%OB!Mhwpcu6Y{*{U^*sNICMN8UTNPSdoh;oU}2H# zes?9}SWMQY*#2bAW23$of|c?&#o3x>|FhmrAxQ)rQoc>NVo{glSQ=_yE#wWG5BqqD zwd`Yim9P#H!WKl=slWVPO8g{3p5R`S6Y8m`TRtU)G1(zHDv?Q`%GCJGdz1g*8UI@x z{(n!SZ!o=jf(gtnbLXi)SP+dwnPoVdIvM@y=s)25YMAo;2CnzgKUOik`}!;&*Cpd0^OP)Y_%6crA@;{YX#1mw6}bLU`M+-<>k?I6 z;>fE?Ysq&T(*f3h6Ig#hnP$$^ec3f>O-kQTW=T`v>RAt#2RzP2&8Sx1hK$Z<4*ihL za`h*K4=0Sew$kgC=?nk=Kf;s9{)9&t5yh?b^?xj6Ue>_@HMj{heXXlGqSm$Ij(5%{ zI7O#ZTN|>UPkuHZAMN5677lS}ERqjzx8wTj%gQ|Nm*Mazh?_i?As1;xn~qe#0}_4x zm2)ofYEPAXkLp-Ye&B5hdNbVAI2!{r=ibqZPyh{s>UDLb!PWtTLGNpKT4LseWeD2E zHTn4wPWMi=f}*rGBwlCRGf)fY_6&!7cXB_$_9KTa!X;Dyv}!s2lZPdmqW!cx1Nv&` zNCQedS3dZ`BFSgJ(lXxa_d69v9ipU`AFO5-H+&o~*pC1N6$^%c>J*#V3*a6u2GIDm zscI3))MASmFYBqo3UZ05Sw8?o z1N{~%`eh_~Xic?M+K+SC^&3 zJ$+tUx4qy8Mzh)Wf%uvzo01xa)fwIq2SSuisx}wKyQ4hQThn|j7?$4MZoU$+;({Ko zvGU|%!=CtrOs$RM+mY+I5Wh%3(oJ&my|5+Y@zpd+IPLna;wWR8Jvp4)Ny9Pvt;YLB zs>(D&1xog`dEW!}d`hJE?Cm9*JGFmw@`k6UDDuw=53kFE!LkP!x0NZ~WLdAMOXnSu zT#rjUQ`N8DR8^Lq5??)_U9vc_1PYeL|1x(|bh|qFWxJ0}=SkjTemrVN*LfVldidD2 zlN;4uBv$S~))5=7ewk7?WPgZBDt;OkzV|gywz6N8?G`caMm)m3b*d=xnpkz3s!l_a zlPmX!)7`@sNs|YhpB0@4{cIJj1MT!Eo|do8c*>r;*j{P5j~yYNY!`-sqp$-kR~24$l~cS|1ed09ov0n+v19XRx3O@=e#N@~2C} zu>M6DmljQInChy#CYE9aM|hpoNADPHT?KTT{GF_Y$qKk zT$DsgHrSa~9TWt@hTCet$c2_a`&v+bwEG<|>g(`AO4Ewv=+hnrp#>;L;`^#3ivXlv>&sv{2< z@-rvU-!X>ePv&P$D+lJAGp10(3^bmUpW(AF;FwAv zy9VrO%>WqU;xgR{qK0o})=u$J`pzv5ED4N>Bx7K$gqy9S$R=vzX>0T3n3_VkYq!3j zszHFS<@b_REQ2dS7Ia+}sK%)NY;_A-@bPWjUcwWt7hfmXH;fwLNuox7D78eYvi59fLvVJ!ihWiK)F7?wl&ixqU&Y?XQ@Scc3Wa z8xQ62#mr}qvO3ENwDcxD7mmG}A2NKohXa(J69=xhf>NDpZxZY{weBmd|hftm_W_|JwWV zs3xzj->4{B1QcIIWpXH5s)CAujA@IO3I(dv;uPWt0){Xr5JD6xXdP%p1r3n;Dj*_6 z!4S*@h#Hk4$`nb+02B~00|pXENb;S4Aog9~UH7iJm);;+0QNaz42Dw~$>RkB1u$g8Lr`Pkr-MKNv+1_$0t*N>*CX z0r55Q(C>_BQAkBn6Vr|x7`UAR()ph@=yE^{?Xgb#0LL0;-uIJFlB02JR;KL%flb^FMej!P z5IFb-3S5aah`%lyb|;t>RELNBj{n85d(=Gf)0asxqCLvH`eVE2>otQSo5dhqRW;%( zL|C7CO1`<^pFYZZ=Iawo>*KJD03N-0s|sK3+M&-^tu(A1COvNmC)(`W=a65-ro0b}*WKk6$3#F^twX z9$h;Ku64Gok|TtqS$0q9EY(WsIN1b2-vP@w1Y|cw9PWw4z|y1Mq$~}{H#1eOkiL-e zeng?{Y4byuvW~AQ+HG_&X5NT6H^OtEr@^j!bw^Q(Bz?;RV>mc|$P-gz_|X8PQ^(%l~^@{EESJ*Lx|L85(JFHd%Nml}QSJhvMEjAZ>6sWwS? z1^XELDm-nA`E>OYR-2Jd(^p+<3~()ok7TbcuZ`j+y1@2sdDfueZle9MT=8dH_ol;v z0m2Jcs3UvLeeL3E(LC3l_kI~Oku8<%3$BThnUYw;N-~jdK)Zx)cn3<<{B0>c{oUw! z&#&{NcEx8kpRlD*UAf^5bHRF`oT;X)7E8|+9s`lxjci8 z@`f*xLESVRlRfd@LGIEuyKyo6UsK;4MMvJ`=eZpYpJ4hY47w0xB7N-{tB80^rt}{^ z0n!@At8#7TaU>wIgj49hfySB(k!}M9DacJ4znwG6>X|3n<-Hpe;i7fm7@mXLgzOqC z{eKSg6=-lqU3(sk`;RVg;(C@HKT0-g^hC?vZZ%VK032-Ct&1c7m_SU|JOn-*YiVP} zr-9K$by9kl7Nue$Kzu$KNntV`aQXbjO#4vx^I7uO@y=V7(ZgXgq^$tvja2goV=$ON zbJjNDr@(2YA)z@RX;&0q-|Tkxka<&NRzfB-phU~imrwTnMh6ikw|0ePM`U?7Jl-=b zkFF~E1w$U&TdH3&tj9OzpoXSmY*3ZNd*B2GF*C@;sdZpB|IHei2^ww(VeA7Tw$(V! z1DnFdOdt38piDLv(|IdmeM=;UmO%@3H?tujAowo11pqc4e-R+9Cz7rr3pVbeRTb105a58~k0P zSF%sLy?S<$+v4HS%Lge}lJB+GZMbym{Z%>`Y(bym6F~W$d9XFZx|b znB_fY!4ud`{04FrX;`l*k^*uHwdxe=cPxb-aYBeF$c(fxLpR@N8P7yU z(@pk1L^=KPcQvSXonBez6uIIQdASOlfn8EmYsoL+qoBkk5O@g)VT{LvNWT-H{CJ4w zT)|31Hl5P_dz#!)dZ%tFKStD^yWsC}JZOxFYf}K18jdRI{N+934(6fzanu(4mz{gS z)eF6)-flT>Ig4~**(cz2kr~?eDycB|-YIf3cDdKtON+K-x8NOivcbuye##%sS76{s zPvPbAOb158)&>76Gy__`S?Qkz=X{6WYlRU52gC)A>ab%b(qZrL%~#%v+R-domIS{jdM!X~rGrcUD^b zX;$Uhx8yotjWV#pPw!EKi|-E@u4$s7gGA)wGIDGA#7A z33z`v=bi)V3ic<`b7ocvV-9~?@V-_TyKd+`L=aC1^mG3J>eQ zDd^`nE*miI)^{;6_Ag>#1@xq^=#6!>Dn0(s3i9d|fMc+AjTgB&>d3GIAHre-|Mf_L zLZ82)n%rcUr8`~yW1gIGt-7HI5LcDu_7;ja z7f%HagucPCIGy1El+%x_a1TieAdTi#~Q1;2x=aq%)=G&iH&I-L(o`$WjP``S~ps zJe-OhMOKHX^O~f+M>Argp>3lu#U^fkWV4ZEt78E|fs)`NcDdxM`_@&nHGb3qdH1>} z8A5uF(toc{f7RHF>%!SWt5vo$YJAQLb3FvOoY5pV5nhx{!e<1JbO`)#H=Ix4)C)R$ zlPx2(hegUn7wid3+;WdCh_U&!)&ggXwuZiSwOK@0QPP$Ss+;BYiqR2;zfImKdIoy! z!mN|R{B2S{0#Sa=!VXe?wo*^e&N>C9Od_$~p=V_KKDJ(gwpmDP?kmOyGYzUwOictX zvUd%F1TUHrWf-A-aOOt*lmG%%^%qS~wr@KyGbPKU#udxpgv8Sz^=rCJ7SJxw<@d{4 zJ<7XhA9VaYh5!GhkQhFg{5`~N=ajZ!;x2s=1kqgopbbYF`!+#@MIV&sf-`{$Ia&DI zgswUDCRxq`3`v*CNV%|w?yg!kL>5Qwl_ksvvC(*c`MZ#p0t)k3!-qjmov{yCR72fn zIqT%?bCr6l8h`ZFlbC?^OV)RpoY`vcu#o2S*CxoGduM!Bbk(VO@a#HpJ3sR{3Vm`8*7HU2SNDXOsy3BR+;kU ztro{4$cVP$R!4+}RTb$W4)8AY#nnlWc~Rk%0e>oSUqn;C#%UKP7*)Q*chH~Z2FCcf z+VGAtl5c3$07x6yhst%-TGC+5)DN~E^-HnFBOdm?f=x6lxSvc;F+JJ$ zVf6t^pBWrP4n+-UNIZpaB1TW5l*Mt@C$mDU#KbE0yPH2}gbD~>+;_euA4K8h{D&$p zX;51RlByXy*9RB(wgaz#nLZf5K#lHfoBb~Gx9_ZIWGn|pSqGfwNE0%%RHfosG)Igm zj=ke}6;F@w7Q zu8NC|MZKIaAgcNzVK`GYj$C`zm?^3<+JK%hl0M}ookDvrTZSw+QI(>od<(xSvPU(K zzG1wa&*s5A(#WBe^Kq5>68XUCc4Q5eL&C0rJJn*1$!{KwSXS`hw0uvk1*Phhz&Gm! z^Q`2|8Zh+skE*prX2bKagIU#ZtKM+6vcbF~+|J#6Nh7&8SuF0eG0ez1X(vckwDI~& zVHq{9Ie$_82SieLCOg(j66V<9t7WQRIny9xAs+?b^=D<{oY3Z?hh>oh}9*i`3z9gWn zYD4XU0z50gY?n3^F~DOJ$-_0=;eliaJ;@y&@|S@OTMRoCw-@18yO)ZTM@t!us8@#%W3gQ#Zi$s(wm<@4{2Zs)B@P@0lJ8D87FvQmjoI3>molS0y59ufH>QIG9D zQyN}WY&@ix$IqTbd-$ey%dTP z6|oQD$65aK`PdHT57IfgtRrBnYWsni28R4Kq=CVvd>%aA(^<^nA!rfY2Z$JRJ0h7H z%q9=IqlvyTj4jmRiX9E{l^Mfc%~ku{k_V5Fl*dc6GSr&x4y|*3!NW0f`<<2ODdc+U z^c*DqV#c|?!Jj=RMNo!bR9MXdHZk9~>p$ zL3^FrJ%OcGIlWV6g?hoH@pRRupm%VN2;PBE*3~*w$ePwpj8rUfGNJj8F^B=GN&LPi zSjvANh)xeMR|m~o%H%K%3JWS#F zP#+nC+RKB#5M5ZAM1z}`a^kgo{%W*(1DZ_GJyZ3!XO@cBcFG;q_;c#zG`M7SyfU6D zmYiS`5n>7Lo`rwt9zj*oLK<#R#qbkN>DY}L)!?WHt*-)SR|Y(*AG~nW-FStQz`a9| ze`AMg`1kwF!QKY)i0`@@m1&h^pv7Y{W?8bFHsDC|Eadyun!QOj;CmcV$t+4mH;mil z6>p(-h@`AEjYO1oo;S>M&FQ3C*%DME4XFwf1q?kK*)mOqVLZ-dKdPsKB`;Gtpwm(9 zbjzns5nJBDv&kx(l`ASoiYX1YSc!|2u1TM)^l{KUQiyms`kT84NVrUVH;Fm1U zTa96~))n`6JE=4VqR6&KBlp7#8~VHqaJORn_sLy4j*d{-oiVLxrsris`YmLkf&S`g z+Wlk>G9;!WLR>|tXrEs=6y(^AcREqZWWf(m4-jjw45$!Jco{lT+_#QA&@ku{*_I$zgRn~&5(swWiT!B%4OTtP~C* zkf?#fEP~Vl5aF>PddhnD-Y?NUvYo0A<}Ig5DmXyajzEW7vmK4Pe1AeTf9siOL)??-N3WU%rCOWv}ccY`&Fmq}=y*&qt zd<9=W2Z^d1E;c?C9N@7JFi+KwwvG4S!HivQn;Ss2pvXI_-r_l%Qi&>YSKM5_${^Qs z;9?EN!;suDCUzn=`9lT6zfMg2${F3nJu@8(WBctanh(w8$Kjhakx+W)mY@jSe0~g` z!>d@=#VyV_>=%&CNHK*hSu;K_7}(bK!i5qdsElxO5j}nr)kl;_T2@BJJy#S0%!bH% zF;J_v?s8g*o^kTW$J;lcttdiRAr{ryq>kAdbBJK1Hf>ZJkhz^c3NcV_3zh~{n@<=% zRR04=ZM$~n+&-yCEWo|PeP5b4G2bTN5f3KkaK*oMqMF;FKmwwu=J00M+$Za%hF1#d z!^HlIem6bI=-`?I4GU;o)h6u%8lLFC%9Wwq82sh5rZAF7*%op_Kpyat=A{YMl~yuV z4d(Sl+9MSToS~PlT4+iVVwa{UelO+We#r<}&IoFy6PhANEolvX&NRvJ3vntSRyR*J zyA+S0GV~>(V|P1!1Y~ZDJPR2*hNxit%I@ddm0TcrCt-?Nc?)QeZzja&DUILYN^_`P zKx4N=u#0`0tG@LNq*G;YIYu?AKm7VMq8A>iDA$fM9I8x4xVUp+jREB7D%-Fc)y6rJ zC^y)RgrwKoxLSo{ke^DE!M%|j(7ag6URyFu4&!w4(1P@jlS@^&F$7|@?=lZ%#v;Dq zVyedjSWnPXyAwvd9`4{ebRf4g^K}H#51$uMg&$t-G9X&V#{opE9pv}3K*IpBXbO3z(^EhQet475!~J{9 zPBYH=DMn>Zl0}g09XbifjhSc8xc~ys^MiR?7*b&Q!S-C-YCjCt(Y=ie zP2(P4D*}ps@-$Gf)r~*818rLmOpQfU@LOPY4jx)%`xfwp#z5f=fLeRyTuTI+xhMPc z(EmLGfnIYS?9Ee+jp7yaAoXAB+{9(~Y2Q~JQlom?pRne$0r+e@C*0tar{G(`98>Fx z`_ML%%AvZs=7O9%TRPnvPqZ zt~tFJ%4Pf4pl)r3W0g!->LSJ zR;YVm-fH|+3nr9q{qY5u+)Meetjcy9!{SZ~R!eL!gU+4wj0!KnG~&63M)FBGJ*1$T z7w4(?g3nHZLxkJMJ^xLnT}g?NdIt@vFF{|GeA1OrL+$r(T~0m(yNwx$)UmK zLIU@eT>7daML~{`otGFuXg}zzHEsyKzf9$&k5od*Jm_o*vZHsIz!ZZ1LkHe8Z_1V> z!J_yP%5XNUORjxW`g(}qdVe3T>J|QfjTAuLmH6XM+W7H#{%NU0Sowdk2@;VMs!-hh zN-+MA+uq~;VpOgR5Ku|nFMx~6b7bU-S7O+K$X8e|wYm0UHY6(bt}Ts_!1{xx6DM!IB}B6mnj z-y7#0pKS+OFwr5mDT-D(V0#fp<)3IIkl)xXNhMQzl&$F-%WbSSjCG58H4Ml%?h|9& zI^trO)mX$cf?>q)VP8>p4I7IZbkUQjPdDC(V+!2~Y5OCR75KpZLV_f*Yof39hrSIq zFr^POb}8U13m$-r+>l!@WO1!h6&(ffWYKRU^0zm$n_CD(;9zI#Fr38Gl*Sx-1?LoU zOC=mc7!g)4-bD>Uq`ect->YrV&|Td8_sU4z*%9AK0LV|bMYBT%u*z7idE_>m?$rd)_%mgA`VgMzS2?M)^Zt}#qn8n1Sqmp*i#Lb!vWS@l&=50CI33}@7E zVVI5~&X8Zope{HX$EoQaXrwxvf^ade!6eh>1={OLAT4Mb z2q60KGOj|TTu3WiiH3@qV=+?8iq%A^hOSfUafPu;6T06DR}fmeFQ*X$<0OS!4lwkQ zvIHXuhF+#xF=;kHGx{wU5JU}TIW&BvNg;A1seAS>$KgxtI^&dbpYZNN69NBi`PwNv z1+YG>&IsACQBUGP;tq#345U4eZ>5M;Xw{u1db0G;5#n z{iH5`4rcx@L~h#k=maDSXQaNMngt2gnaH3Qd0KO&nL-~@4;T^v?&E-WxVK^g+@Jek zdjPnH>A*d3J34R=;--V&PJnw;o!vJX2lo`6iT`~9+;0bQLke(VAa1bL#SH+AejfV2 zK_JTUo%KFwy5^~R2E<;+g4rFL{(ZH3rHsVHyd9tI$!Bupe;N~1)z3*9OMH?a8sy$w zKk25C!I@3{QKQ#)tvo{3jy>uXSsG2kcYOZ~hg?aPe+r7hZBS!poHW&ur=SDpfrVXO zrZ86$AASRy) zlfj-?1@8hoZS4fMpbvq%xxLq2L?Z5P?iyIyIaREAiX!?gGE=T5^&z-0H|!An_|vSE z^frrBMRHxUvQ^)4*5n+y1?pk6Qt3|eKok34!YTRc;JJLPcY4E(x~|eAC>sZL4iK!VdGt27}WIu2j2lnLz zLc4I{b!aDepkc@+a~6ybI=Str zrH}zc{7Y`v79o+;awAm6Id25%ip!u_9L|bgnhb4ZW0mvyaVWfqqKa18)=-tC1YO{8 zQMf@*l9*(Tn$NG>lT^#R4{&^ER-4lQ#vAi05A@*}WUbTI(+W1(I$YPhr72ZGqgTzS zWjoL9L%=D;0~Ju`L-v|Obe;oMG?Gx0g+L7^Evt%j-omZBQy5*ZVsJV&7uO#&x>P)!7h!iZ0W1CItDd zEUte?*Cq*!!4oF$Y|CM$jS4< z{Pp}86Ud6ywzn_zeF;=4>RW`{+8HPJo;3*Tb_V>S_ko|xK+A)_bfs|6elsEECZ;V< zL67V!m47<10kT5ZvL zbmmu!XYSyk*0J07#2!5qd(7oX^fB-cWb?*NTQ_Xlv|+Q;&zm>8IBa!sa9Fo-qszvP kH9y{@e$oMfJQ^CD@Sk_Mx6n*q_gXu)`)w=z?qJG)0GkJXg8%>k literal 0 HcmV?d00001 diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 0291a34a6..8fcb478b2 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 USDTieredSTOLogic = artifacts.require('./USDTieredSTO.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'); @@ -143,10 +146,26 @@ 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 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) - return deployer.deploy(GeneralTransferManagerFactory, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(GeneralTransferManagerFactory, 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) @@ -162,11 +181,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, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(EtherDividendCheckpointFactory, 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, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(ERC20DividendCheckpointFactory, 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) @@ -268,17 +287,14 @@ module.exports = function (deployer, network, accounts) { // G) Once the CappedSTOFactory 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(CappedSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // Deploy the proxy factory - return deployer.deploy(USDTieredSTOProxyFactory, {from: PolymathAccount}); + return moduleRegistry.verifyModule(CappedSTOFactory.address, true, {from: PolymathAccount}) }).then(() => { // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). - return deployer.deploy(USDTieredSTOFactory, usdTieredSTOSetupCost, 0, 0, USDTieredSTOProxyFactory.address, {from: PolymathAccount}) + return deployer.deploy(USDTieredSTOFactory, 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. - return moduleRegistry.registerModule(USDTieredSTOFactory.address, {from: PolymathAccount}) + return moduleRegistry.registerModule(USDTieredSTOFactory.address, {from: PolymathAccount}) }).then(()=>{ // J) Once the USDTieredSTOFactory 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. @@ -303,16 +319,19 @@ module.exports = function (deployer, network, accounts) { POLYOracle: ${POLYOracle} STFactory: ${STFactory.address} + GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} CappedSTOFactory: ${CappedSTOFactory.address} USDTieredSTOFactory: ${USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} + USDTieredSTOLogic: ${USDTieredSTOLogic.address} 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 c4517ae4f..82f078fe6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "polymath-core", - "version": "1.4.0", + "version": "2.0.0", "description": "Polymath Network Core Smart Contracts", "main": "truffle.js", "directories": { @@ -29,8 +29,9 @@ "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-proxyFactories": "sol-merger './contracts/modules/STO/ProxyFactory/*.sol' ./flat/modules/STO/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", + "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 && npm run flatten-proxyFactories", "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\"" @@ -67,10 +68,10 @@ "ethers": "^4.0.7", "fs": "0.0.2", "openzeppelin-solidity": "2.0.0", + "prompt": "^1.0.0", "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.2.0", @@ -86,7 +87,6 @@ "eslint-plugin-standard": "^4.0.0", "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", 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/scripts/docs.sh b/scripts/docs.sh index db7aba417..af7f6e395 100755 --- a/scripts/docs.sh +++ b/scripts/docs.sh @@ -32,12 +32,21 @@ 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..." diff --git a/scripts/tokenInfo.js b/scripts/tokenInfo-v1.js similarity index 53% rename from scripts/tokenInfo.js rename to scripts/tokenInfo-v1.js index 2df8c57c4..ea14a7efe 100644 --- a/scripts/tokenInfo.js +++ b/scripts/tokenInfo-v1.js @@ -1,19 +1,18 @@ 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/")); +var request = require('request-promise') -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); +const securityTokenABI = JSON.parse(require('fs').readFileSync('../CLI/data/SecurityToken1-4-0.json').toString()).abi; +const generalTransferManagerABI = JSON.parse(require('fs').readFileSync('../CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; 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) + 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) await getInfo(tokenAddress); } } @@ -32,7 +31,7 @@ async function getInfo(tokenAddress) { 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}); + let gtmEvents = await getLogsFromEtherscan(gtmRes.moduleAddress, web3.utils.hexToNumber('0x5C5C18'), 'latest', 'LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); console.log("Count of GeneralTransferManager Events: " + gtmEvents.length); console.log("Modules Attached (TransferManager):"); await getModules(2, token); @@ -65,4 +64,41 @@ async function getModules(type, token) { } } -getTokens(); +async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignature) { + let urlDomain = '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 = '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); +} + +getTokens(); \ No newline at end of file diff --git a/scripts/tokenInfo-v2.js b/scripts/tokenInfo-v2.js new file mode 100644 index 000000000..1d0f9236f --- /dev/null +++ b/scripts/tokenInfo-v2.js @@ -0,0 +1,108 @@ +const Web3 = require("web3"); +const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/")); +var request = require('request-promise') + +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; + +async function getTokens() { + const securityTokenRegistryAddress = "0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97"; + const securityTokenRegistryABI = await getABIfromEtherscan(securityTokenRegistryAddress); + const securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); + + let logs = await getLogsFromEtherscan(securityTokenRegistry.options.address, 0, 'latest', 'NewSecurityToken(string,string,address,address,uint256,address,bool,uint256)'); + console.log(logs.length); + for (let i = 0; i < logs.length; i++) { + let tokenAddress = '0x' + logs[i].topics[1].slice(26, 66) + await getInfo(tokenAddress); + } +} + +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("Details: " + await token.methods.tokenDetails().call()); + console.log("Symbol: " + await token.methods.symbol().call()); + console.log("Granularity: " + await token.methods.granularity().call()); + console.log("Total Supply: " + await token.methods.totalSupply().call()); + console.log("Transfers Frozen: " + await token.methods.transfersFrozen().call()); + console.log("Minting Frozen: " + await token.methods.mintingFrozen().call()); + let controllerDisabled = await token.methods.controllerDisabled().call(); + if (controllerDisabled) { + console.log("Controller disabled: YES"); + } else { + console.log("Controller: " + await token.methods.controller().call()); + } + console.log("Investors: " + await token.methods.getInvestorCount().call()); + console.log("Latest Checkpoint: " + await token.methods.currentCheckpointId().call()); + let gtmEventsCount = 0; + let gtmModules = await token.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + for (const m of gtmModules) { + let gtmEvents = await getLogsFromEtherscan(m, 9299699, 'latest', 'ModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); + gtmEventsCount += gtmEvents.length; + } + console.log("Count of GeneralTransferManager Events: " + gtmEventsCount); + 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("Modules Attached (Burn):"); + await getModules(5, token); + console.log(); + console.log(); +} + +async function getModules(type, token) { + let modules = await token.methods.getModulesByType(type).call(); + for (const m of modules) { + let moduleData = await token.methods.getModule(m).call(); + console.log(" Name: " + web3.utils.toAscii(moduleData[0])); + console.log(" Address: " + m); + } +} + +async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignature) { + let urlDomain = '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 = '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); +} + +getTokens(); \ No newline at end of file diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index c40ed53de..18531ffb8 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"]; @@ -130,7 +130,7 @@ contract("CappedSTO", accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); - + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -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, @@ -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(); @@ -427,17 +417,8 @@ 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( - web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("0.1111", "ether") - }) - ); - }); - - 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 refund pending amount", async () => { + await I_SecurityToken_ETH.changeGranularity(10 ** 21, {from: token_owner}); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, fromTime, @@ -448,15 +429,26 @@ 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({ 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); @@ -554,7 +546,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, @@ -793,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, @@ -806,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); @@ -855,7 +857,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"); @@ -993,7 +995,7 @@ 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); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index ae7fe9527..62cb7223b 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); @@ -348,6 +353,119 @@ 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[2].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 () => { assert.equal(await I_CountTransferManagerFactory.getSetupCost.call(), 0); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index edd9e4282..f41b5575d 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 cf1f5b073..89202579b 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 a6f680738..6203d3574 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 db692515f..fefe3208b 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -8,18 +8,20 @@ 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"); -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 USDTieredSTO = artifacts.require("./USDTieredSTO"); 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"); @@ -41,14 +43,16 @@ let I_TrackedRedemptionFactory; let I_ScheduledCheckpointFactory; let I_MockBurnFactory; let I_MockWrongTypeBurnFactory; -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; @@ -61,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; @@ -82,7 +87,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); @@ -129,8 +136,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(0, 0, 0, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -194,7 +213,7 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -256,18 +275,6 @@ export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyI return new Array(I_VolumeRestrictionTransferManagerFactory); } -export async function deploySingleTradeVolumeRMAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_SingleTradeVolumeRestrictionManagerFactory = await SingleTradeVolumeRestrictionManagerFactory.new(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, setupCost) { I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); assert.notEqual( @@ -338,9 +345,9 @@ export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstan } export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({from: accountPolymath}); + I_USDTieredSTOLogic = await USDTieredSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: accountPolymath }); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, 0, 0, I_USDTieredSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), @@ -356,7 +363,8 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst /// Deploy the Dividend Modules export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, 0, 0, I_ERC20DividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -368,7 +376,8 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns } export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, 0, 0, I_EtherDividendCheckpointLogic.address, { from: accountPolymath }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 31d7b194f..1345e6fe5 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; diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 28fb2f31a..8df86241e 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 })); }); @@ -550,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 () => { diff --git a/test/k_module_registry.js b/test/k_module_registry.js index bfdf91eca..57ce3508c 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -479,7 +479,7 @@ contract("ModuleRegistry", accounts => { let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; - let sto3 = (await I_MRProxied.getModulesByType.call(3))[2]; + let sto3 = (await I_MRProxied.getModulesByType.call(3))[2]; let sto4 = (await I_MRProxied.getModulesByType.call(3))[3]; assert.equal(sto1, I_CappedSTOFactory1.address); @@ -542,7 +542,7 @@ contract("ModuleRegistry", accounts => { I_MRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) ); }); - + it("Should successfully reclaim POLY tokens -- not authorised", async() => { catchRevert( I_MRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) @@ -592,7 +592,7 @@ contract("ModuleRegistry", accounts => { I_ReclaimERC20.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) ); }); - + it("Should successfully reclaim POLY tokens -- not authorised", async() => { catchRevert( I_ReclaimERC20.reclaimERC20(I_PolyToken.address, { from: account_temp }) @@ -614,7 +614,7 @@ contract("ModuleRegistry", accounts => { describe("Test case for the PolymathRegistry", async() => { it("Should successfully get the address -- fail because key is not exist", async() => { - catchRevert( + catchRevert( I_PolymathRegistry.getAddress("PolyOracle") ); }); @@ -624,6 +624,35 @@ contract("ModuleRegistry", accounts => { assert.equal(_moduleR, I_ModuleRegistryProxy.address); }) }) + + + describe("Test cases for the transferOwnership", async() => { + + it("Should fail to transfer the ownership -- not authorised", async() => { + catchRevert( + I_MRProxied.transferOwnership(account_temp, { from: account_issuer}) + ); + }); + + it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { + catchRevert( + I_MRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) + ); + }); + + it("Should successfully transfer the ownership of the STR", async() => { + let tx = await I_MRProxied.transferOwnership(account_temp, { from: account_polymath }); + assert.equal(tx.logs[0].args.previousOwner, account_polymath); + assert.equal(tx.logs[0].args.newOwner, account_temp); + }); + + it("New owner has authorisation", async() => { + let tx = await I_MRProxied.transferOwnership(account_polymath, { from: account_temp }); + assert.equal(tx.logs[0].args.previousOwner, account_temp); + assert.equal(tx.logs[0].args.newOwner, account_polymath); + }); + + }) }); }); }); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index aa11c1ba8..e889c79d0 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, web3.utils.toWei("500", "ether")); - + // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index d4394206a..cc2b1fdca 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -945,6 +945,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should get the tickers by owner", async () => { let tickersList = await I_STRProxied.getTickersByOwner.call(token_owner); + console.log(tickersList); assert.equal(tickersList.length, 4); let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); console.log(tickersListArray); diff --git a/test/o_security_token.js b/test/o_security_token.js index e1c8d708a..a5ce2636f 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/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1e46c8d1a..928504634 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) @@ -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, 0); @@ -329,22 +329,22 @@ contract("USDTieredSTO", accounts => { 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(), + (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].ratePerTierDiscountPoly.call(i)).toNumber(), + (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].tokensPerTierTotal.call(i)).toNumber(), + (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].tokensPerTierDiscountPoly.call(i)).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config" ); @@ -514,22 +514,22 @@ contract("USDTieredSTO", accounts => { 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(), + (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].ratePerTierDiscountPoly.call(i)).toNumber(), + (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].tokensPerTierTotal.call(i)).toNumber(), + (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].tokensPerTierDiscountPoly.call(i)).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config" ); @@ -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; @@ -865,22 +904,22 @@ contract("USDTieredSTO", accounts => { { from: ISSUER } ); assert.equal( - (await I_USDTieredSTO_Array[stoId].ratePerTier.call(0)).toNumber(), + (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].ratePerTierDiscountPoly.call(0)).toNumber(), + (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].tokensPerTierTotal.call(0), + (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].tokensPerTierDiscountPoly.call(0), + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[3], BigNumber(15 * 10 ** 20).toNumber(), "STO Configuration doesn't set as expected" ); @@ -989,25 +1028,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 +2882,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()); @@ -3732,6 +3764,196 @@ 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); + + 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; + let tierId = 0; + let investment_Tokens = BigNumber(10.5).mul(10**18); + 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, false, "TOKEN", "ETH", refund_Tokens); + + 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; @@ -3757,6 +3979,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; @@ -3840,8 +4086,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 +4097,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 +4273,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); @@ -4236,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 () => { @@ -4306,12 +4564,12 @@ 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"); 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"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 971681b73..1b58c3e03 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 @@ -299,22 +299,22 @@ contract("USDTieredSTO Sim", accounts => { 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(), + (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].ratePerTierDiscountPoly.call(i)).toNumber(), + (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].tokensPerTierTotal.call(i)).toNumber(), + (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].tokensPerTierDiscountPoly.call(i)).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), _tokensPerTierDiscountPoly[stoId][i].toNumber(), "Incorrect _tokensPerTierDiscountPoly in config" ); @@ -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] ) ); } diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 636acdc28..222db8a0d 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, STOSetupCost); @@ -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; diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 0add841b2..21d562ca7 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(0, 0, 0, { + let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 97e8931b4..9e664b1c5 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, 0); [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, 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 2cb1e663e..9dfccbec8 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/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js deleted file mode 100644 index 1af45c54c..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, 0); - [P_SingleTradeVolumeRestrictionManagerFactory] = await deploySingleTradeVolumeRMAndVerified(account_polymath, I_MRProxied, 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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = SecurityToken.at(tx.logs[2].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..13865df0a --- /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 Fuzz', 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, 0); + // STEP 6: Deploy the GeneralDelegateManagerFactory + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + + // Deploy Modules + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); + + [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, 0); + + [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, 0); + + [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, 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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[2].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 - paid module", 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 - free module", 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); + }; + }); + }); + +}); diff --git a/yarn.lock b/yarn.lock index 33dc876ee..aa591815d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -324,6 +324,10 @@ async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: 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" @@ -1860,6 +1864,10 @@ deep-assign@^2.0.0: 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" @@ -3420,6 +3428,10 @@ 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" @@ -4415,7 +4427,7 @@ mkdirp-promise@^5.0.1: 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" dependencies: @@ -4493,7 +4505,7 @@ mustache@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" -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" @@ -4537,6 +4549,10 @@ 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" + needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" @@ -5007,6 +5023,14 @@ pkg-dir@^1.0.0: 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" @@ -5062,6 +5086,17 @@ promise-to-callback@^1.0.0: 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" @@ -5226,6 +5261,12 @@ read-pkg@^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" @@ -5464,13 +5505,17 @@ 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" + 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.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" dependencies: @@ -5720,7 +5765,7 @@ shelljs@^0.7.4: 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" dependencies: @@ -6608,6 +6653,17 @@ util@^0.10.3: 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" @@ -7046,6 +7102,18 @@ 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" + winston@^2.3.1: version "2.4.4" resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" From d7434902777e5f304623cb8c47e52b563b449371 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 17 Dec 2018 16:25:23 +0200 Subject: [PATCH 043/119] Split out ISTO.sol --- contracts/interfaces/ISTO.sol | 13 +++++++++++++ contracts/modules/STO/CappedSTO.sol | 6 +++--- contracts/modules/STO/DummySTO.sol | 6 +++--- contracts/modules/STO/PreSaleSTO.sol | 6 +++--- contracts/modules/STO/{ISTO.sol => STO.sol} | 12 ++++-------- .../modules/STO/{ISTOStorage.sol => STOStorage.sol} | 4 ++-- contracts/modules/STO/USDTieredSTO.sol | 12 ++++++++---- contracts/proxy/USDTieredSTOProxy.sol | 4 ++-- 8 files changed, 38 insertions(+), 25 deletions(-) create mode 100644 contracts/interfaces/ISTO.sol rename contracts/modules/STO/{ISTO.sol => STO.sol} (88%) 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..ab3d6b3ff --- /dev/null +++ b/contracts/interfaces/ISTO.sol @@ -0,0 +1,13 @@ +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); + +} \ No newline at end of file diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 17c4da3e2..63ae261fa 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/utils/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 @@ -141,7 +141,7 @@ contract CappedSTO is ISTO, ReentrancyGuard { /** * @notice Return the total no. of tokens sold */ - function getTokensSold() public view returns (uint256) { + function getTokensSold() external view returns (uint256) { return totalTokensSold; } diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index ad6bb6f74..78d161012 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"; @@ -76,7 +76,7 @@ contract DummySTO is ISTO { /** * @notice Returns the total no. of investors */ - function getTokensSold() public view returns (uint256) { + function getTokensSold() external view returns (uint256) { return 0; } diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 5290a9e38..4bd77ba59 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"; @@ -51,7 +51,7 @@ contract PreSaleSTO is ISTO { /** * @notice Returns the total no. of tokens sold */ - function getTokensSold() public view returns (uint256) { + function getTokensSold() external view returns (uint256) { return totalTokensSold; } diff --git a/contracts/modules/STO/ISTO.sol b/contracts/modules/STO/STO.sol similarity index 88% rename from contracts/modules/STO/ISTO.sol rename to contracts/modules/STO/STO.sol index 8e162574b..ef5d028a8 100644 --- a/contracts/modules/STO/ISTO.sol +++ b/contracts/modules/STO/STO.sol @@ -3,13 +3,14 @@ pragma solidity ^0.4.24; import "../../Pausable.sol"; import "../Module.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "./ISTOStorage.sol"; +import "./STOStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../../interfaces/ISTO.sol"; /** - * @title Interface to be implemented by all STO modules + * @title Base abstract contract to be extended 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, DAI } @@ -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) */ 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..aecfaf3d7 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; diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 33c9bacfa..2c1bfced9 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 "./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"; @@ -713,7 +713,11 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { * @notice Return the total no. of tokens sold * @return uint256 Total number of tokens sold */ - function getTokensSold() public view returns (uint256) { + function getTokensSold() external view returns (uint256) { + return _getTokensSold(); + } + + function _getTokensSold() internal view returns (uint256) { if (isFinalized) return totalTokensSold; else @@ -820,7 +824,7 @@ contract USDTieredSTO is USDTieredSTOStorage, ISTO, ReentrancyGuard { rate, fundsRaisedUSD, investorCount, - getTokensSold(), + _getTokensSold(), _fundRaiseTypes ); } diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol index c0f4c4201..6df4c8cf4 100644 --- a/contracts/proxy/USDTieredSTOProxy.sol +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -4,13 +4,13 @@ import "../modules/STO/USDTieredSTOStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/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 From 8996ea41c17df83f843a1b19c5887c4b5c0152b7 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 18 Dec 2018 11:47:21 +0200 Subject: [PATCH 044/119] Split out ITransferManager.sol --- .../ITransferManager.sol | 20 ++++++------------- .../Mixed/ScheduledCheckpoint.sol | 6 +++--- .../LockupVolumeRestrictionTM.sol | 6 +++--- .../SingleTradeVolumeRestrictionTM.sol | 6 +++--- .../TransferManager/CountTransferManager.sol | 6 +++--- .../GeneralTransferManager.sol | 6 +++--- .../ManualApprovalTransferManager.sol | 6 +++--- .../PercentageTransferManager.sol | 6 +++--- .../TransferManager/TransferManager.sol | 19 ++++++++++++++++++ contracts/tokens/SecurityToken.sol | 2 +- 10 files changed, 47 insertions(+), 36 deletions(-) rename contracts/{modules/TransferManager => interfaces}/ITransferManager.sol (61%) create mode 100644 contracts/modules/TransferManager/TransferManager.sol diff --git a/contracts/modules/TransferManager/ITransferManager.sol b/contracts/interfaces/ITransferManager.sol similarity index 61% rename from contracts/modules/TransferManager/ITransferManager.sol rename to contracts/interfaces/ITransferManager.sol index a8cfa4475..384b3aa9d 100644 --- a/contracts/modules/TransferManager/ITransferManager.sol +++ b/contracts/interfaces/ITransferManager.sol @@ -1,13 +1,9 @@ pragma solidity ^0.4.24; -import "../../Pausable.sol"; -import "../Module.sol"; - /** * @title Interface to be implemented by all Transfer Manager modules - * @dev abstract contract */ -contract ITransferManager is Module, Pausable { +interface ITransferManager { //If verifyTransfer returns: // FORCE_VALID, the transaction will always be valid, regardless of other TM results @@ -16,13 +12,9 @@ contract ITransferManager is Module, Pausable { // NA, then the result from this TM is ignored enum Result {INVALID, NA, VALID, FORCE_VALID} - function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data, bool _isTransfer) public returns(Result); - - function unpause() public onlyOwner { - super._unpause(); - } + /** + * @notice Determines if the transfer between these two accounts can happen + */ + function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data, bool _isTransfer) external returns(Result); - function pause() public onlyOwner { - super._pause(); - } -} +} \ No newline at end of file diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index 13bc29d18..e838f78e6 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -1,14 +1,14 @@ pragma solidity ^0.4.24; import "./../../Checkpoint/ICheckpoint.sol"; -import "../../TransferManager/ITransferManager.sol"; +import "../../TransferManager/TransferManager.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 { +contract ScheduledCheckpoint is ICheckpoint, TransferManager { using SafeMath for uint256; struct Schedule { @@ -85,7 +85,7 @@ contract ScheduledCheckpoint is ICheckpoint, ITransferManager { * @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) { + function verifyTransfer(address /* _from */, address /* _to */, uint256 /* _amount */, bytes /* _data */, bool _isTransfer) external returns(Result) { require(_isTransfer == false || msg.sender == securityToken, "Sender is not owner"); if (paused || !_isTransfer) { return Result.NA; diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index 1397ad832..a4f6b95f6 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -1,10 +1,10 @@ pragma solidity ^0.4.24; -import "./../../TransferManager/ITransferManager.sol"; +import "./../../TransferManager/TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -contract LockupVolumeRestrictionTM is ITransferManager { +contract LockupVolumeRestrictionTM is TransferManager { using SafeMath for uint256; @@ -66,7 +66,7 @@ contract LockupVolumeRestrictionTM is ITransferManager { * @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) external 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 diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol index 6406dd013..8dd1d3a66 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol @@ -1,13 +1,13 @@ pragma solidity ^0.4.24; -import "./../../TransferManager/ITransferManager.sol"; +import "./../../TransferManager/TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager for limiting volume of tokens in a single trade */ -contract SingleTradeVolumeRestrictionTM is ITransferManager { +contract SingleTradeVolumeRestrictionTM is TransferManager { using SafeMath for uint256; bytes32 constant public ADMIN = "ADMIN"; @@ -63,7 +63,7 @@ contract SingleTradeVolumeRestrictionTM is ITransferManager { bytes /* _data */, bool /* _isTransfer */ ) - public + external returns(Result) { bool validTransfer; diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 1d11f6865..d95559665 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -1,11 +1,11 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "./TransferManager.sol"; /** * @title Transfer Manager for limiting maximum number of token holders */ -contract CountTransferManager is ITransferManager { +contract CountTransferManager is TransferManager { // The maximum number of concurrent token holders uint256 public maxHolderCount; @@ -36,7 +36,7 @@ contract CountTransferManager is ITransferManager { bytes /* _data */, bool /* _isTransfer */ ) - public + external returns(Result) { if (!paused) { diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 7b830d375..36b742f90 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,13 +1,13 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "./TransferManager.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 GeneralTransferManagerStorage, TransferManager { using SafeMath for uint256; @@ -141,7 +141,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, ITransferManag * @param _from Address of the sender * @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 */) external returns(Result) { if (!paused) { if (allowAllTransfers) { //All transfers allowed, regardless of whitelist diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 621161a32..29131f0cb 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -1,12 +1,12 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for manually approving or blocking transactions between accounts */ -contract ManualApprovalTransferManager is ITransferManager { +contract ManualApprovalTransferManager is TransferManager { using SafeMath for uint256; //Address from which issuances come @@ -84,7 +84,7 @@ contract ManualApprovalTransferManager is ITransferManager { * @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) external 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 diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index 61cbf437a..191a2a6a5 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -7,13 +7,13 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Transfer Manager module for limiting percentage of token supply a single address can hold */ -contract PercentageTransferManager is ITransferManager { +contract PercentageTransferManager is TransferManager { using SafeMath for uint256; // Permission key for modifying the whitelist @@ -53,7 +53,7 @@ contract PercentageTransferManager is ITransferManager { * @param _to Address of the receiver * @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 */) external returns(Result) { if (!paused) { if (_from == address(0) && allowPrimaryIssuance) { return Result.NA; diff --git a/contracts/modules/TransferManager/TransferManager.sol b/contracts/modules/TransferManager/TransferManager.sol new file mode 100644 index 000000000..08d7f3385 --- /dev/null +++ b/contracts/modules/TransferManager/TransferManager.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.24; + +import "../../Pausable.sol"; +import "../Module.sol"; +import "../../interfaces/ITransferManager.sol"; + +/** + * @title Base abstract contract to be implemented by all Transfer Manager modules + */ +contract TransferManager is ITransferManager, Module, Pausable { + + function unpause() public onlyOwner { + super._unpause(); + } + + function pause() public onlyOwner { + super._pause(); + } +} diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 3c27d7d94..7cf13fa28 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -6,7 +6,7 @@ import "../interfaces/IModule.sol"; import "../interfaces/IModuleFactory.sol"; import "../interfaces/IModuleRegistry.sol"; import "../interfaces/IFeatureRegistry.sol"; -import "../modules/TransferManager/ITransferManager.sol"; +import "../interfaces/ITransferManager.sol"; import "../RegistryUpdater.sol"; import "../libraries/Util.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; From d842c207c63a9a4569a7ae64c05695d2c91decf9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Tue, 18 Dec 2018 12:29:04 +0200 Subject: [PATCH 045/119] added TransferManagerEnums --- contracts/interfaces/ITransferManager.sol | 11 +++-------- contracts/interfaces/TransferManagerEnums.sol | 15 +++++++++++++++ .../modules/TransferManager/TransferManager.sol | 2 +- contracts/tokens/SecurityToken.sol | 8 ++++---- 4 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 contracts/interfaces/TransferManagerEnums.sol diff --git a/contracts/interfaces/ITransferManager.sol b/contracts/interfaces/ITransferManager.sol index 384b3aa9d..b5819c63d 100644 --- a/contracts/interfaces/ITransferManager.sol +++ b/contracts/interfaces/ITransferManager.sol @@ -1,20 +1,15 @@ pragma solidity ^0.4.24; +import "./TransferManagerEnums.sol"; + /** * @title Interface to be implemented by all Transfer Manager modules */ interface ITransferManager { - //If verifyTransfer returns: - // FORCE_VALID, the transaction will always be valid, regardless of other TM results - // INVALID, then the transfer should not be allowed regardless of other TM results - // VALID, then the transfer is valid for this TM - // NA, then the result from this TM is ignored - enum Result {INVALID, NA, VALID, FORCE_VALID} - /** * @notice Determines if the transfer between these two accounts can happen */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data, bool _isTransfer) external returns(Result); + function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data, bool _isTransfer) external returns(TransferManagerEnums.Result); } \ No newline at end of file diff --git a/contracts/interfaces/TransferManagerEnums.sol b/contracts/interfaces/TransferManagerEnums.sol new file mode 100644 index 000000000..2b7e85853 --- /dev/null +++ b/contracts/interfaces/TransferManagerEnums.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.24; + +/** + * @title Container contract for transfer manager enums + */ +contract TransferManagerEnums { + + //If verifyTransfer returns: + // FORCE_VALID, the transaction will always be valid, regardless of other TM results + // INVALID, then the transfer should not be allowed regardless of other TM results + // VALID, then the transfer is valid for this TM + // NA, then the result from this TM is ignored + enum Result {INVALID, NA, VALID, FORCE_VALID} + +} \ No newline at end of file diff --git a/contracts/modules/TransferManager/TransferManager.sol b/contracts/modules/TransferManager/TransferManager.sol index 08d7f3385..5d8cde83d 100644 --- a/contracts/modules/TransferManager/TransferManager.sol +++ b/contracts/modules/TransferManager/TransferManager.sol @@ -7,7 +7,7 @@ import "../../interfaces/ITransferManager.sol"; /** * @title Base abstract contract to be implemented by all Transfer Manager modules */ -contract TransferManager is ITransferManager, Module, Pausable { +contract TransferManager is ITransferManager, TransferManagerEnums, Module, Pausable { function unpause() public onlyOwner { super._unpause(); diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 7cf13fa28..14bb43c01 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -632,12 +632,12 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater 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) { + TransferManagerEnums.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _data, _isTransfer); + if (valid == TransferManagerEnums.Result.INVALID) { isInvalid = true; - } else if (valid == ITransferManager.Result.VALID) { + } else if (valid == TransferManagerEnums.Result.VALID) { isValid = true; - } else if (valid == ITransferManager.Result.FORCE_VALID) { + } else if (valid == TransferManagerEnums.Result.FORCE_VALID) { isForceValid = true; } } From 1bee21614df426ca2a2d6ab9a5993f1cb5230e45 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 31 Dec 2018 14:16:39 +0200 Subject: [PATCH 046/119] ISecurityToken interface changed according to SecurityToken (#495) * ISecurityToken interface changed according to SecurityToken * verifyTransfer external --- contracts/interfaces/ISecurityToken.sol | 80 ++++++++++++++++--------- contracts/tokens/SecurityToken.sol | 25 ++++---- 2 files changed, 64 insertions(+), 41 deletions(-) diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index f280d6c19..c2b7ed76f 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -18,14 +18,23 @@ 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 the result of verifyTransfer - function verifyTransfer(address _from, address _to, uint256 _value) external returns (bool success); + /** + * @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 + * @param _value Value of transfer + * @param _data Data to indicate validation + * @return bool + */ + function verifyTransfer(address _from, address _to, uint256 _value, bytes _data) external returns (bool); /** * @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 + * @return success */ function mint(address _investor, uint256 _value) external returns (bool success); @@ -56,9 +65,15 @@ interface ISecurityToken { 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) + /** + * @notice Validate permissions with PermissionManager if it exists, If no Permission return false + * @dev Note that IModule withPerm will allow ST owner all permissions anyway + * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) + * @param _delegate address of delegate + * @param _module address of PermissionManager module + * @param _perm the permissions + * @return success + */ function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns (bool); /** @@ -68,12 +83,10 @@ interface ISecurityToken { * @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 - + * @return uint8 Array of module types + * @return bytes32 Module label */ - function getModule(address _module) external view returns(bytes32, address, address, bool, uint8, uint256, uint256); + function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[], bytes32); /** * @notice Returns module list for a module name @@ -107,6 +120,12 @@ interface ISecurityToken { */ function createCheckpoint() external returns (uint256); + /** + * @notice Gets list of times that checkpoints were created + * @return List of checkpoint times + */ + function getCheckpointTimes() external view 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 @@ -137,13 +156,6 @@ interface ISecurityToken { */ 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. @@ -153,11 +165,12 @@ interface ISecurityToken { function withdrawERC20(address _tokenContract, uint256 _value) external; /** - * @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; + function changeModuleBudget(address _module, uint256 _change, bool _increase) external; /** * @notice Changes the tokenDetails @@ -171,14 +184,6 @@ interface ISecurityToken { */ 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 */ @@ -203,6 +208,24 @@ interface ISecurityToken { */ function mintMulti(address[] _investors, uint256[] _values) external returns (bool success); + /** + * @notice Attachs a module to the SecurityToken + * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it + * @dev to control restrictions on transfers. + * @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 the module. + * @param _budget max amount of ongoing POLY willing to assign to the module. + * @param _label custom module label. + */ + function addModuleWithLabel( + address _moduleFactory, + bytes _data, + uint256 _maxCost, + uint256 _budget, + bytes32 _label + ) external; + /** * @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 @@ -213,6 +236,7 @@ interface ISecurityToken { * @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) + * @param _budget max amount of ongoing POLY willing to assign to the module. */ function addModule( address _moduleFactory, diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 14bb43c01..298561a2b 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -214,17 +214,16 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater securityTokenVersion = SemanticVersion(2,0,0); } - // /** - // * @notice Attachs a module to the SecurityToken - // * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it - // * @dev to control restrictions on transfers. - // * @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 the module. - // * @param _budget max amount of ongoing POLY willing to assign to the module. - // * @param _label custom module label. - // */ - + /** + * @notice Attachs a module to the SecurityToken + * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it + * @dev to control restrictions on transfers. + * @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 the module. + * @param _budget max amount of ongoing POLY willing to assign to the module. + * @param _label custom module label. + */ function addModuleWithLabel( address _moduleFactory, bytes _data, @@ -344,7 +343,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return address module address * @return address module factory address * @return bool module archived - * @return uint8 module type + * @return uint8 array of module types + * @return bytes32 module label */ function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[], bytes32) { return (modulesToData[_module].name, @@ -386,7 +386,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater } /** - * @notice allows owner to increase/decrease POLY approval of one of the modules * @param _module module address * @param _change change in allowance From 247b64ee1a53ee561c80afd8ba6a45f40f8bbee2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 31 Dec 2018 15:52:38 +0200 Subject: [PATCH 047/119] Standardize proxy approach (#485) * created proxy for CappedSTO * fixed tests * proxy for PreSaleSTO * fixed tests for ModuleRegistry * removed redundant imports * proxy for DummySTO * proxy for CountTransferManager * proxy for ManualApprovalTransferManager * moved constants to storages * proxy for PercentageTransferManager * fixed tests * proxy for GeneralPermissionManager * typos in deployGTMAndVerifyed * updated tests for CappedSTO --- contracts/mocks/MockFactory.sol | 5 +- contracts/mocks/TestSTOFactory.sol | 5 +- .../GeneralPermissionManager.sol | 14 +----- .../GeneralPermissionManagerFactory.sol | 11 ++-- .../GeneralPermissionManagerStorage.sol | 18 +++++++ contracts/modules/STO/CappedSTO.sol | 14 +----- contracts/modules/STO/CappedSTOFactory.sol | 14 ++++-- contracts/modules/STO/CappedSTOStorage.sol | 19 +++++++ contracts/modules/STO/DummySTO.sol | 12 +---- contracts/modules/STO/DummySTOFactory.sol | 13 +++-- contracts/modules/STO/DummySTOStorage.sol | 17 +++++++ contracts/modules/STO/PreSaleSTO.sol | 7 +-- contracts/modules/STO/PreSaleSTOFactory.sol | 14 ++++-- contracts/modules/STO/PreSaleSTOStorage.sol | 12 +++++ .../TransferManager/CountTransferManager.sol | 8 +-- .../CountTransferManagerFactory.sol | 14 ++++-- .../CountTransferManagerStorage.sol | 13 +++++ .../ManualApprovalTransferManager.sol | 28 +---------- .../ManualApprovalTransferManagerFactory.sol | 11 ++-- .../ManualApprovalTransferManagerStorage.sol | 33 ++++++++++++ .../PercentageTransferManager.sol | 16 +----- .../PercentageTransferManagerFactory.sol | 14 ++++-- .../PercentageTransferManagerStorage.sol | 21 ++++++++ contracts/proxy/CappedSTOProxy.sol | 32 ++++++++++++ contracts/proxy/CountTransferManagerProxy.sol | 30 +++++++++++ contracts/proxy/DummySTOProxy.sol | 32 ++++++++++++ .../proxy/GeneralPermissionManagerProxy.sol | 32 ++++++++++++ .../ManualApprovalTransferManagerProxy.sol | 30 +++++++++++ .../proxy/PercentageTransferManagerProxy.sol | 30 +++++++++++ contracts/proxy/PreSaleSTOProxy.sol | 32 ++++++++++++ migrations/2_deploy_contracts.js | 50 +++++++++++++++---- test/b_capped_sto.js | 30 ++++------- test/helpers/createInstances.js | 40 +++++++++++---- test/i_Issuance.js | 12 +---- test/k_module_registry.js | 21 +++++--- test/u_module_registry_proxy.js | 5 +- 36 files changed, 533 insertions(+), 176 deletions(-) create mode 100644 contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol create mode 100644 contracts/modules/STO/CappedSTOStorage.sol create mode 100644 contracts/modules/STO/DummySTOStorage.sol create mode 100644 contracts/modules/STO/PreSaleSTOStorage.sol create mode 100644 contracts/modules/TransferManager/CountTransferManagerStorage.sol create mode 100644 contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol create mode 100644 contracts/modules/TransferManager/PercentageTransferManagerStorage.sol create mode 100644 contracts/proxy/CappedSTOProxy.sol create mode 100644 contracts/proxy/CountTransferManagerProxy.sol create mode 100644 contracts/proxy/DummySTOProxy.sol create mode 100644 contracts/proxy/GeneralPermissionManagerProxy.sol create mode 100644 contracts/proxy/ManualApprovalTransferManagerProxy.sol create mode 100644 contracts/proxy/PercentageTransferManagerProxy.sol create mode 100644 contracts/proxy/PreSaleSTOProxy.sol diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 170fdb1e3..73f5aaa27 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -15,9 +15,10 @@ contract MockFactory is DummySTOFactory { * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - DummySTOFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) { } diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index da5dc32fc..f9fad0c4e 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -9,9 +9,10 @@ contract TestSTOFactory is DummySTOFactory { * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - DummySTOFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) { version = "1.0.0"; name = "TestSTO"; diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 7dca72ce5..6c41a25ce 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -2,22 +2,12 @@ pragma solidity ^0.4.24; import "./IPermissionManager.sol"; import "../Module.sol"; +import "./GeneralPermissionManagerStorage.sol"; /** * @title Permission Manager module for core permissioning functionality */ -contract GeneralPermissionManager is IPermissionManager, Module { - - // Mapping used to hold the permissions on the modules provided to delegate, module add => delegate add => permission bytes32 => bool - mapping (address => mapping (address => mapping (bytes32 => bool))) public perms; - // Mapping hold the delagate details - mapping (address => bytes32) public delegateDetails; - // Array to track all delegates - address[] public allDelegates; - - - // Permission flag - bytes32 public constant CHANGE_PERMISSION = "CHANGE_PERMISSION"; +contract GeneralPermissionManager is GeneralPermissionManagerStorage, 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); diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index a353b7e26..77792b2b7 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -1,28 +1,33 @@ pragma solidity ^0.4.24; -import "./GeneralPermissionManager.sol"; import "../ModuleFactory.sol"; +import "../../proxy/GeneralPermissionManagerProxy.sol"; /** * @title Factory for deploying GeneralPermissionManager module */ contract GeneralPermissionManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; name = "GeneralPermissionManager"; title = "General Permission Manager"; description = "Manage permissions within the Security Token and attached modules"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -31,7 +36,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { */ function deploy(bytes /* _data */) external returns(address) { address polyToken = _takeFee(); - address permissionManager = new GeneralPermissionManager(msg.sender, polyToken); + address permissionManager = new GeneralPermissionManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); return permissionManager; diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol new file mode 100644 index 000000000..3a1a43513 --- /dev/null +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the GeneralPermissionManager storage + */ +contract GeneralPermissionManagerStorage { + + // Mapping used to hold the permissions on the modules provided to delegate, module add => delegate add => permission bytes32 => bool + mapping (address => mapping (address => mapping (bytes32 => bool))) public perms; + // Mapping hold the delagate details + mapping (address => bytes32) public delegateDetails; + // Array to track all delegates + address[] public allDelegates; + + // Permission flag + bytes32 public constant CHANGE_PERMISSION = "CHANGE_PERMISSION"; + +} diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 63ae261fa..1cdc08984 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -4,24 +4,14 @@ import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "./CappedSTOStorage.sol"; /** * @title STO module for standard capped crowdsale */ -contract CappedSTO is STO, ReentrancyGuard { +contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { using SafeMath for uint256; - // Determine whether users can invest on behalf of a beneficiary - bool public allowBeneficialInvestments = false; - // 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 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; - /** * Event for token purchase logging * @param purchaser who paid for the tokens diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 25f02cd8b..24bf5de06 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -1,29 +1,35 @@ pragma solidity ^0.4.24; -import "./CappedSTO.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; +import "../../proxy/CappedSTOProxy.sol"; +import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying CappedSTO module */ contract CappedSTOFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "1.0.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."; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,9 +39,9 @@ contract CappedSTOFactory is ModuleFactory { function deploy(bytes _data) external returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function - CappedSTO cappedSTO = new CappedSTO(msg.sender, polyToken); + CappedSTOProxy cappedSTO = new CappedSTOProxy(msg.sender, polyToken, logicContract); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == cappedSTO.getInitFunction(), "Invalid data"); + require(Util.getSig(_data) == IBoot(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*/ diff --git a/contracts/modules/STO/CappedSTOStorage.sol b/contracts/modules/STO/CappedSTOStorage.sol new file mode 100644 index 000000000..51afb048e --- /dev/null +++ b/contracts/modules/STO/CappedSTOStorage.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the CappedSTO storage + */ +contract CappedSTOStorage { + + // Determine whether users can invest on behalf of a beneficiary + bool public allowBeneficialInvestments = false; + // 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 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; + +} \ No newline at end of file diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 78d161012..cdd770ac7 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -2,23 +2,15 @@ pragma solidity ^0.4.24; import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; +import "./DummySTOStorage.sol"; /** * @title STO module for sample implementation of a different crowdsale module */ -contract DummySTO is STO { - - bytes32 public constant ADMIN = "ADMIN"; - - uint256 public investorCount; - - uint256 public cap; - string public someString; +contract DummySTO is DummySTOStorage, STO { event GenerateTokens(address _investor, uint256 _amount); - mapping (address => uint256) public investors; - /** * @notice Constructor * @param _securityToken Address of the security token diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index dc2f9dd56..ac3e3cb79 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -1,21 +1,25 @@ pragma solidity ^0.4.24; -import "./DummySTO.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; +import "../../proxy/DummySTOProxy.sol"; +import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying DummySTO module */ contract DummySTOFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; @@ -24,6 +28,7 @@ contract DummySTOFactory is ModuleFactory { description = "Dummy STO"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,9 +38,9 @@ contract DummySTOFactory is ModuleFactory { function deploy(bytes _data) external returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function - DummySTO dummySTO = new DummySTO(msg.sender, polyToken); + DummySTOProxy dummySTO = new DummySTOProxy(msg.sender, polyToken, logicContract); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == dummySTO.getInitFunction(), "Invalid data"); + require(Util.getSig(_data) == IBoot(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*/ diff --git a/contracts/modules/STO/DummySTOStorage.sol b/contracts/modules/STO/DummySTOStorage.sol new file mode 100644 index 000000000..5e841b261 --- /dev/null +++ b/contracts/modules/STO/DummySTOStorage.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the DummySTO storage + */ +contract DummySTOStorage { + + bytes32 public constant ADMIN = "ADMIN"; + + uint256 public investorCount; + + uint256 public cap; + string public someString; + + mapping (address => uint256) public investors; + +} \ No newline at end of file diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 4bd77ba59..dbc0bccfb 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -3,19 +3,16 @@ pragma solidity ^0.4.24; import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "./PreSaleSTOStorage.sol"; /** * @title STO module for private presales */ -contract PreSaleSTO is STO { +contract PreSaleSTO is PreSaleSTOStorage, STO { using SafeMath for uint256; - bytes32 public constant PRE_SALE_ADMIN = "PRE_SALE_ADMIN"; - event TokensAllocated(address _investor, uint256 _amount); - mapping (address => uint256) public investors; - /** * @notice Constructor * @param _securityToken Address of the security token diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index 29aabbe7e..a1103ac0d 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -1,29 +1,35 @@ pragma solidity ^0.4.24; -import "./PreSaleSTO.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; +import "../../proxy/PreSaleSTOProxy.sol"; +import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying PreSaleSTO module */ contract PreSaleSTOFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; name = "PreSaleSTO"; title = "PreSale STO"; description = "Allows Issuer to configure pre-sale token allocations"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -34,9 +40,9 @@ contract PreSaleSTOFactory is ModuleFactory { function deploy(bytes _data) external returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function - PreSaleSTO preSaleSTO = new PreSaleSTO(msg.sender, polyToken); + PreSaleSTOProxy preSaleSTO = new PreSaleSTOProxy(msg.sender, polyToken, logicContract); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == preSaleSTO.getInitFunction(), "Invalid data"); + require(Util.getSig(_data) == IBoot(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*/ diff --git a/contracts/modules/STO/PreSaleSTOStorage.sol b/contracts/modules/STO/PreSaleSTOStorage.sol new file mode 100644 index 000000000..956284e3d --- /dev/null +++ b/contracts/modules/STO/PreSaleSTOStorage.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the PreSaleSTO storage + */ +contract PreSaleSTOStorage { + + bytes32 public constant PRE_SALE_ADMIN = "PRE_SALE_ADMIN"; + + mapping (address => uint256) public investors; + +} \ No newline at end of file diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index d95559665..64f4af91f 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -1,16 +1,12 @@ pragma solidity ^0.4.24; import "./TransferManager.sol"; +import "./CountTransferManagerStorage.sol"; /** * @title Transfer Manager for limiting maximum number of token holders */ -contract CountTransferManager is TransferManager { - - // The maximum number of concurrent token holders - uint256 public maxHolderCount; - - bytes32 public constant ADMIN = "ADMIN"; +contract CountTransferManager is CountTransferManagerStorage, TransferManager { event ModifyHolderCount(uint256 _oldHolderCount, uint256 _newHolderCount); diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index 7f16203da..b0b714fdc 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -1,29 +1,35 @@ pragma solidity ^0.4.24; -import "./CountTransferManager.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; +import "../../proxy/CountTransferManagerProxy.sol"; +import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying CountTransferManager module */ contract CountTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "2.1.0"; name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,8 +39,8 @@ contract CountTransferManagerFactory is ModuleFactory { */ function deploy(bytes _data) external returns(address) { address polyToken = _takeFee(); - CountTransferManager countTransferManager = new CountTransferManager(msg.sender, polyToken); - require(Util.getSig(_data) == countTransferManager.getInitFunction(), "Provided data is not valid"); + CountTransferManagerProxy countTransferManager = new CountTransferManagerProxy(msg.sender, polyToken, logicContract); + require(Util.getSig(_data) == IBoot(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*/ diff --git a/contracts/modules/TransferManager/CountTransferManagerStorage.sol b/contracts/modules/TransferManager/CountTransferManagerStorage.sol new file mode 100644 index 000000000..1c17e62d9 --- /dev/null +++ b/contracts/modules/TransferManager/CountTransferManagerStorage.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the CountTransferManager storage + */ +contract CountTransferManagerStorage { + + bytes32 public constant ADMIN = "ADMIN"; + + // The maximum number of concurrent token holders + uint256 public maxHolderCount; + +} diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 29131f0cb..382ffb486 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -2,38 +2,14 @@ pragma solidity ^0.4.24; import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "./ManualApprovalTransferManagerStorage.sol"; /** * @title Transfer Manager module for manually approving or blocking transactions between accounts */ -contract ManualApprovalTransferManager is TransferManager { +contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, TransferManager { 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, diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index fe4d532dd..9a087adfd 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -1,28 +1,33 @@ pragma solidity ^0.4.24; -import "./ManualApprovalTransferManager.sol"; import "../ModuleFactory.sol"; +import "../../proxy/ManualApprovalTransferManagerProxy.sol"; /** * @title Factory for deploying ManualApprovalTransferManager module */ contract ManualApprovalTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "2.0.1"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -31,7 +36,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { */ function deploy(bytes /* _data */) external returns(address) { address polyToken = _takeFee(); - address manualTransferManager = new ManualApprovalTransferManager(msg.sender, polyToken); + address manualTransferManager = new ManualApprovalTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(manualTransferManager); diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol new file mode 100644 index 000000000..cc7e55d49 --- /dev/null +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the ManualApprovalTransferManager storage + */ +contract ManualApprovalTransferManagerStorage { + + //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; + +} diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index 191a2a6a5..3fe58381e 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -9,26 +9,14 @@ pragma solidity ^0.4.24; import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "./PercentageTransferManagerStorage.sol"; /** * @title Transfer Manager module for limiting percentage of token supply a single address can hold */ -contract PercentageTransferManager is TransferManager { +contract PercentageTransferManager is PercentageTransferManagerStorage, TransferManager { using SafeMath for uint256; - // Permission key for modifying the whitelist - bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant ADMIN = "ADMIN"; - - // Maximum percentage that any holder can have, multiplied by 10**16 - e.g. 20% is 20 * 10**16 - uint256 public maxHolderPercentage; - - // Ignore transactions which are part of the primary issuance - bool public allowPrimaryIssuance = true; - - // Addresses on this list are always able to send / receive tokens - mapping (address => bool) public whitelist; - event ModifyHolderPercentage(uint256 _oldHolderPercentage, uint256 _newHolderPercentage); event ModifyWhitelist( address _investor, diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 3f858ade0..cecc759f7 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -1,29 +1,35 @@ pragma solidity ^0.4.24; -import "./PercentageTransferManager.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; +import "../../proxy/PercentageTransferManagerProxy.sol"; +import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying PercentageTransferManager module */ contract PercentageTransferManagerFactory is ModuleFactory { + address public logicContract; + /** * @notice Constructor * @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 (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { + require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; name = "PercentageTransferManager"; title = "Percentage Transfer Manager"; description = "Restrict the number of investors"; compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + logicContract = _logicContract; } /** @@ -33,8 +39,8 @@ contract PercentageTransferManagerFactory is ModuleFactory { */ function deploy(bytes _data) external returns(address) { address polyToken = _takeFee(); - PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender, polyToken); - require(Util.getSig(_data) == percentageTransferManager.getInitFunction(), "Provided data is not valid"); + PercentageTransferManagerProxy percentageTransferManager = new PercentageTransferManagerProxy(msg.sender, polyToken, logicContract); + require(Util.getSig(_data) == IBoot(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*/ diff --git a/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol b/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol new file mode 100644 index 000000000..4656b200a --- /dev/null +++ b/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.4.24; + +/** + * @title Contract used to store layout for the PercentageTransferManager storage + */ +contract PercentageTransferManagerStorage { + + // Permission key for modifying the whitelist + bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant ADMIN = "ADMIN"; + + // Maximum percentage that any holder can have, multiplied by 10**16 - e.g. 20% is 20 * 10**16 + uint256 public maxHolderPercentage; + + // Ignore transactions which are part of the primary issuance + bool public allowPrimaryIssuance = true; + + // Addresses on this list are always able to send / receive tokens + mapping (address => bool) public whitelist; + +} diff --git a/contracts/proxy/CappedSTOProxy.sol b/contracts/proxy/CappedSTOProxy.sol new file mode 100644 index 000000000..90084e5dc --- /dev/null +++ b/contracts/proxy/CappedSTOProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; +import "../modules/STO/STOStorage.sol"; +import "../modules/ModuleStorage.sol"; +import "../modules/STO/CappedSTOStorage.sol"; + +/** + * @title CappedSTO module Proxy + */ +contract CappedSTOProxy is CappedSTOStorage, STOStorage, 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/contracts/proxy/CountTransferManagerProxy.sol b/contracts/proxy/CountTransferManagerProxy.sol new file mode 100644 index 000000000..2c030ba89 --- /dev/null +++ b/contracts/proxy/CountTransferManagerProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/CountTransferManagerStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title CountTransferManager module Proxy + */ +contract CountTransferManagerProxy is CountTransferManagerStorage, 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/DummySTOProxy.sol b/contracts/proxy/DummySTOProxy.sol new file mode 100644 index 000000000..8ff44a887 --- /dev/null +++ b/contracts/proxy/DummySTOProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; +import "../modules/STO/STOStorage.sol"; +import "../modules/ModuleStorage.sol"; +import "../modules/STO/DummySTOStorage.sol"; + +/** + * @title DummySTO module Proxy + */ +contract DummySTOProxy is DummySTOStorage, STOStorage, 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/contracts/proxy/GeneralPermissionManagerProxy.sol b/contracts/proxy/GeneralPermissionManagerProxy.sol new file mode 100644 index 000000000..8fff0061b --- /dev/null +++ b/contracts/proxy/GeneralPermissionManagerProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; +import "../modules/STO/STOStorage.sol"; +import "../modules/ModuleStorage.sol"; +import "../modules/PermissionManager/GeneralPermissionManagerStorage.sol"; + +/** + * @title GeneralPermissionManager module Proxy + */ +contract GeneralPermissionManagerProxy is GeneralPermissionManagerStorage, 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/contracts/proxy/ManualApprovalTransferManagerProxy.sol b/contracts/proxy/ManualApprovalTransferManagerProxy.sol new file mode 100644 index 000000000..366298d59 --- /dev/null +++ b/contracts/proxy/ManualApprovalTransferManagerProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/ManualApprovalTransferManagerStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + @title ManualApprovalTransferManager module Proxy + */ +contract ManualApprovalTransferManagerProxy is ManualApprovalTransferManagerStorage, 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/PercentageTransferManagerProxy.sol b/contracts/proxy/PercentageTransferManagerProxy.sol new file mode 100644 index 000000000..c5c93560f --- /dev/null +++ b/contracts/proxy/PercentageTransferManagerProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.4.24; + +import "../modules/TransferManager/PercentageTransferManagerStorage.sol"; +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "../modules/ModuleStorage.sol"; + +/** + * @title PercentageTransferManager module Proxy + */ +contract PercentageTransferManagerProxy is PercentageTransferManagerStorage, 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/PreSaleSTOProxy.sol b/contracts/proxy/PreSaleSTOProxy.sol new file mode 100644 index 000000000..895cf3fdf --- /dev/null +++ b/contracts/proxy/PreSaleSTOProxy.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.4.24; + +import "./OwnedProxy.sol"; +import "../Pausable.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; +import "../modules/STO/STOStorage.sol"; +import "../modules/ModuleStorage.sol"; +import "../modules/STO/PreSaleSTOStorage.sol"; + +/** + * @title PreSaleSTO module Proxy + */ +contract PreSaleSTOProxy is PreSaleSTOStorage, STOStorage, 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 8fcb478b2..4a28d2d67 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,10 +1,13 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') +const GeneralPermissionManagerLogic = artifacts.require('./GeneralPermissionManager.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') +const PercentageTransferManagerLogic = artifacts.require('./PercentageTransferManager.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') const USDTieredSTOLogic = artifacts.require('./USDTieredSTO.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') +const CountTransferManagerLogic = artifacts.require('./CountTransferManager.sol') const EtherDividendCheckpointLogic = artifacts.require('./EtherDividendCheckpoint.sol') const ERC20DividendCheckpointLogic = artifacts.require('./ERC20DividendCheckpoint.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') @@ -12,7 +15,9 @@ const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpo const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol') +const ManualApprovalTransferManagerLogic = artifacts.require('./ManualApprovalTransferManager.sol') const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol') +const CappedSTOLogic = artifacts.require("./CappedSTO.sol"); const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol') const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol') const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol') @@ -151,17 +156,37 @@ 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 GeneralPermissionManagerLogic Contract (Factory used to generate the GeneralPermissionManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralPermissionManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the CountTransferManagerLogic Contract (Factory used to generate the CountTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(CountTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the ManualApprovalTransferManagerLogic Contract (Factory used to generate the ManualApprovalTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(ManualApprovalTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // B) Deploy the PercentageTransferManagerLogic Contract (Factory used to generate the PercentageTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(PercentageTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); + }).then(() => { + // 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 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 CappedSTOLogic Contract (Factory used to generate the CappedSTO contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(CappedSTOLogic, "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,15 +194,15 @@ module.exports = function (deployer, network, accounts) { }).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) - return deployer.deploy(GeneralPermissionManagerFactory, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(GeneralPermissionManagerFactory, 0, 0, 0, GeneralPermissionManagerLogic.address, {from: PolymathAccount}); }).then(() => { // 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, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(CountTransferManagerFactory, 0, 0, 0, CountTransferManagerLogic.address, {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) - return deployer.deploy(PercentageTransferManagerFactory, 0, 0, 0, {from: PolymathAccount}); + return deployer.deploy(PercentageTransferManagerFactory, 0, 0, 0, PercentageTransferManagerLogic.address, {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) @@ -187,9 +212,9 @@ module.exports = function (deployer, network, accounts) { // to provide the functionality of the dividend in terms of ERC20 token) return deployer.deploy(ERC20DividendCheckpointFactory, 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) - return deployer.deploy(ManualApprovalTransferManagerFactory, 0, 0, 0, {from: PolymathAccount}); + // 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) + return deployer.deploy(ManualApprovalTransferManagerFactory, 0, 0, 0, ManualApprovalTransferManagerLogic.address, {from: PolymathAccount}); }).then(() => { // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, {from: PolymathAccount}); @@ -278,7 +303,7 @@ module.exports = function (deployer, network, accounts) { return moduleRegistry.verifyModule(ManualApprovalTransferManagerFactory.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, cappedSTOSetupCost, 0, 0, {from: PolymathAccount}) + return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, 0, 0, CappedSTOLogic.address, {from: PolymathAccount}) }).then(() => { // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. // So any securityToken can use that factory to generate the CappedSTOFactory contract. @@ -321,14 +346,19 @@ module.exports = function (deployer, network, accounts) { STFactory: ${STFactory.address} GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerLogic: ${GeneralPermissionManagerLogic.address} GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + CappedSTOLogic: ${CappedSTOLogic.address} CappedSTOFactory: ${CappedSTOFactory.address} - USDTieredSTOFactory: ${USDTieredSTOFactory.address} USDTieredSTOLogic: ${USDTieredSTOLogic.address} + USDTieredSTOFactory: ${USDTieredSTOFactory.address} + CountTransferManagerLogic: ${CountTransferManagerLogic.address} CountTransferManagerFactory: ${CountTransferManagerFactory.address} + PercentageTransferManagerLogic: ${PercentageTransferManagerLogic.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} + ManualApprovalTransferManagerLogic: ${ManualApprovalTransferManagerLogic.address} ManualApprovalTransferManagerFactory: ${ManualApprovalTransferManagerFactory.address} EtherDividendCheckpointLogic: ${EtherDividendCheckpointLogic.address} ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 18531ffb8..a319c0e23 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -2,7 +2,7 @@ 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, deployCappedSTOAndVerifyed } from "./helpers/createInstances"; import { catchRevert } from "./helpers/exceptions"; const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); @@ -133,19 +133,7 @@ contract("CappedSTO", accounts => { // STEP 6: Deploy the CappedSTOFactory - I_CappedSTOFactory = await CappedSTOFactory.new(cappedSTOSetupCost, 0, 0, { from: token_owner }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - address_zero, - "CappedSTOFactory contract was not deployed" - ); - - // STEP 7: Register the Modules with the ModuleRegistry contract - - // (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 }); + [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, cappedSTOSetupCost); // Printing all the contract addresses console.log(` @@ -876,11 +864,11 @@ contract("CappedSTO", accounts => { }); it("Should fail to change the title -- zero length", async () => { - await catchRevert(I_CappedSTOFactory.changeTitle("", { from: token_owner })); + await catchRevert(I_CappedSTOFactory.changeTitle("", { from: account_polymath })); }); it("Should successfully change the title", async () => { - await I_CappedSTOFactory.changeTitle("STO Capped", { from: token_owner }); + await I_CappedSTOFactory.changeTitle("STO Capped", { from: account_polymath }); assert.equal(await I_CappedSTOFactory.title.call(), "STO Capped", "Title doesn't get changed"); }); @@ -889,11 +877,11 @@ contract("CappedSTO", accounts => { }); it("Should fail to change the description -- zero length", async () => { - await catchRevert(I_CappedSTOFactory.changeDescription("", { from: token_owner })); + await catchRevert(I_CappedSTOFactory.changeDescription("", { from: account_polymath })); }); it("Should successfully change the description", async () => { - await I_CappedSTOFactory.changeDescription("It is only a STO", { from: token_owner }); + await I_CappedSTOFactory.changeDescription("It is only a STO", { from: account_polymath }); assert.equal(await I_CappedSTOFactory.description.call(), "It is only a STO", "Description doesn't get changed"); }); @@ -902,16 +890,16 @@ contract("CappedSTO", accounts => { }); it("Should fail to change the name -- zero length", async () => { - await catchRevert(I_CappedSTOFactory.changeName(web3.utils.stringToHex(""), { from: token_owner })); + await catchRevert(I_CappedSTOFactory.changeName(web3.utils.stringToHex(""), { from: account_polymath })); }); it("Should successfully change the name", async () => { - await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), { from: token_owner }); + await I_CappedSTOFactory.changeName(web3.utils.stringToHex("STOCapped"), { from: account_polymath }); 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 }); + await I_CappedSTOFactory.changeName(web3.utils.stringToHex("CappedSTO"), { from: account_polymath }); assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), "CappedSTO", "Name doesn't get changed"); }); }); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index fefe3208b..048ea5060 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -5,6 +5,7 @@ const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); +const CappedSTO = artifacts.require("./CappedSTO.sol"); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); @@ -12,24 +13,29 @@ 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 ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.sol"); const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); +const PercentageTransferManager = artifacts.require("./PercentageTransferManager.sol"); const ScheduledCheckpointFactory = artifacts.require('./ScheduledCheckpointFactory.sol'); const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); const USDTieredSTO = artifacts.require("./USDTieredSTO"); -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 GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); +const CountTransferManager = artifacts.require("./CountTransferManager.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); const VolumeRestrictionTransferManagerFactory = artifacts.require("./LockupVolumeRestrictionTMFactory"); const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); +const PreSaleSTO = artifacts.require("./PreSaleSTO.sol"); const PolyToken = artifacts.require("./PolyToken.sol"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); +const DummySTO = artifacts.require("./DummySTO.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); @@ -43,25 +49,32 @@ let I_TrackedRedemptionFactory; let I_ScheduledCheckpointFactory; let I_MockBurnFactory; let I_MockWrongTypeBurnFactory; +let I_ManualApprovalTransferManagerLogic; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; +let I_PercentageTransferManagerLogic; let I_PercentageTransferManagerFactory; let I_EtherDividendCheckpointLogic; let I_EtherDividendCheckpointFactory; +let I_CountTransferManagerLogic; let I_CountTransferManagerFactory; let I_ERC20DividendCheckpointLogic; let I_ERC20DividendCheckpointFactory; +let I_GeneralPermissionManagerLogic; let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; let I_ModuleRegistryProxy; +let I_PreSaleSTOLogic; let I_PreSaleSTOFactory; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; +let I_CappedSTOLogic; let I_CappedSTOFactory; let I_SecurityToken; +let I_DummySTOLogic; let I_DummySTOFactory; let I_PolyToken; let I_STFactory; @@ -216,9 +229,9 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, set I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), + I_GeneralTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", - "GeneralPermissionManagerFactory contract was not deployed" + "GeneralTransferManagerFactory contract was not deployed" ); // (B) : Register the GeneralDelegateManagerFactory @@ -227,7 +240,8 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, set } export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_CountTransferManagerLogic = await CountTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, 0, 0, I_CountTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_CountTransferManagerFactory.address.valueOf(), @@ -240,7 +254,8 @@ export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, } export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_ManualApprovalTransferManagerLogic = await ManualApprovalTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, 0, 0, ManualApprovalTransferManager.address, { from: accountPolymath }); assert.notEqual( I_ManualApprovalTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -252,7 +267,8 @@ export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxy } export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_PercentageTransferManagerLogic = await PercentageTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, 0, 0, I_PercentageTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_PercentageTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -290,7 +306,8 @@ export async function deployScheduleCheckpointAndVerified(accountPolymath, MRPro /// Deploy the Permission Manager export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, 0, 0, I_GeneralPermissionManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -307,7 +324,8 @@ export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, set /// Deploy the STO Modules export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_DummySTOFactory = await DummySTOFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_DummySTOLogic = await DummySTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_DummySTOFactory = await DummySTOFactory.new(setupCost, 0, 0, I_DummySTOLogic.address,{ from: accountPolymath }); assert.notEqual( I_DummySTOFactory.address.valueOf(), @@ -319,7 +337,8 @@ export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance } export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_CappedSTOLogic = await CappedSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, 0, 0, I_CappedSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_CappedSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -332,7 +351,8 @@ export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstanc } export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_PreSaleSTOLogic = await PreSaleSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, 0, 0, I_PreSaleSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_PreSaleSTOFactory.address.valueOf(), diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 1345e6fe5..b85dea7e1 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -168,17 +168,7 @@ contract("Issuance", accounts => { it("POLYMATH: Should successfully attach the STO factory with the security token", async () => { // STEP 4: Deploy the CappedSTOFactory - I_CappedSTOFactory = await CappedSTOFactory.new(cappedSTOSetupCost, 0, 0, { from: account_polymath }); - - assert.notEqual( - I_CappedSTOFactory.address.valueOf(), - address_zero, - "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 }); + [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, cappedSTOSetupCost); let bytesSTO = encodeModuleCall(STOParameters, [ latestTime() + duration.seconds(5000), diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 57ce3508c..c5e5535a6 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -3,14 +3,16 @@ import { duration, ensureException, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { setUpPolymathNetwork } from "./helpers/createInstances"; +import {deployCappedSTOAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); +const CappedSTO = artifacts.require("./CappedSTO.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); +const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const MockFactory = artifacts.require("./MockFactory.sol"); const TestSTOFactory = artifacts.require("./TestSTOFactory.sol"); @@ -40,6 +42,7 @@ contract("ModuleRegistry", accounts => { let message = "Transaction Should fail!"; // Contract Instance Declaration let I_GeneralPermissionManagerFactory; + let I_GeneralPermissionManagerLogic; let I_GeneralTransferManagerFactory; let I_SecurityTokenRegistryProxy; let I_GeneralPermissionManager; @@ -56,7 +59,7 @@ contract("ModuleRegistry", accounts => { let I_SecurityToken; let I_ReclaimERC20; let I_STRProxied; - let I_CappedSTO; + let I_CappedSTOLogic; let I_PolyToken; let I_MockFactory; let I_TestSTOFactory; @@ -260,13 +263,14 @@ contract("ModuleRegistry", accounts => { }); it("Should fail in registering the module-- type = 0", async () => { - I_MockFactory = await MockFactory.new(0, 0, 0, { from: account_polymath }); + I_MockFactory = await MockFactory.new(0, 0, 0, 0, { from: account_polymath }); catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); }); it("Should fail to register the new module because msg.sender is not the owner of the module", async() => { - I_CappedSTOFactory3 = await CappedSTOFactory.new(0, 0, 0, { from: account_temp }); + I_CappedSTOLogic = await CappedSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + I_CappedSTOFactory3 = await CappedSTOFactory.new(0, 0, 0, I_CappedSTOLogic.address, { from: account_temp }); catchRevert( I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: token_owner }) ); @@ -292,7 +296,7 @@ contract("ModuleRegistry", accounts => { }); it("Should successfully verify the module -- false", async () => { - I_CappedSTOFactory1 = await CappedSTOFactory.new(0, 0, 0, { from: account_polymath }); + I_CappedSTOFactory1 = await CappedSTOFactory.new(0, 0, 0, I_CappedSTOLogic.address, { 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"); @@ -323,7 +327,7 @@ contract("ModuleRegistry", accounts => { }); it("Should fail to register module because custom modules not allowed", async () => { - I_CappedSTOFactory2 = await CappedSTOFactory.new(0, 0, 0, { from: token_owner }); + I_CappedSTOFactory2 = await CappedSTOFactory.new(0, 0, 0, I_CappedSTOLogic.address, { from: token_owner }); assert.notEqual( I_CappedSTOFactory2.address.valueOf(), @@ -376,7 +380,8 @@ contract("ModuleRegistry", accounts => { }) it("Should successfully add verified module", async () => { - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(0, 0, 0, { + I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(0, 0, 0, I_GeneralPermissionManagerLogic.address, { from: account_polymath }); await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); @@ -386,7 +391,7 @@ contract("ModuleRegistry", accounts => { }); it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async () => { - I_TestSTOFactory = await TestSTOFactory.new(0, 0, 0, { from: account_polymath }); + I_TestSTOFactory = await TestSTOFactory.new(0, 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 diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 21d562ca7..91b578a9d 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -12,6 +12,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); +const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -22,6 +23,7 @@ contract("ModuleRegistryProxy", accounts => { let I_SecurityTokenRegistryProxy; let I_GeneralTransferManagerFactory; let I_GeneralPermissionManagerfactory; + let I_GeneralPermissionManagerLogic; let I_MockModuleRegistry; let I_STFactory; let I_PolymathRegistry; @@ -163,7 +165,8 @@ contract("ModuleRegistryProxy", accounts => { describe("Feed some data in storage", async () => { it("Register and verify the new module", async () => { - I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(0, 0, 0, { + I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(0, 0, 0, I_GeneralPermissionManagerLogic.address, { from: account_polymath }); From 8a4beb7c9f69ef56e67a50a082e7443ae0cc72e1 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 31 Dec 2018 17:52:05 +0530 Subject: [PATCH 048/119] resolve conflicts after the merge --- contracts/InternalRegistry.sol | 86 +++ contracts/SecurityTokenRegistry.sol | 961 ++++++++++++++-------------- migrations/2_deploy_contracts.js | 4 + test/n_security_token_registry.js | 324 +++++----- 4 files changed, 740 insertions(+), 635 deletions(-) create mode 100644 contracts/InternalRegistry.sol diff --git a/contracts/InternalRegistry.sol b/contracts/InternalRegistry.sol new file mode 100644 index 000000000..ff60e8ffb --- /dev/null +++ b/contracts/InternalRegistry.sol @@ -0,0 +1,86 @@ +pragma solidity ^0.4.24; + +import "./storage/EternalStorage.sol"; +import "./libraries/Util.sol"; +import "./libraries/Encoder.sol"; + +contract InternalRegistry is EternalStorage { + + // Emit after ticker registration + event RegisterTicker( + address indexed _owner, + string _ticker, + string _name, + uint256 indexed _registrationDate, + uint256 indexed _expiryDate, + bool _fromAdmin, + uint256 _registrationFee + ); + + /** + * @notice Internal - Sets the details of the ticker + */ + function addTicker( + address _owner, + string _ticker, + string _tokenName, + uint256 _registrationDate, + uint256 _expiryDate, + bool _status, + bool _fromAdmin, + uint256 _fee + ) + public + { + _setTickerOwnership(_owner, _ticker); + _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); + } + + /** + * @notice Internal - Sets the ticker owner + * @param _owner is the address of the owner of the ticker + * @param _ticker is the ticker symbol + */ + function _setTickerOwnership(address _owner, string _ticker) internal { + bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); + uint256 length = uint256(getArrayBytes32(_ownerKey).length); + pushArray(_ownerKey, Util.stringToBytes32(_ticker)); + set(Encoder.getKey("tickerIndex", _ticker), length); + bytes32 seenKey = Encoder.getKey("seenUsers", _owner); + if (!getBool(seenKey)) { + pushArray(Encoder.getKey("activeUsers"), _owner); + set(seenKey, true); + } + } + + /** + * @notice Internal - Stores the ticker details + */ + function _storeTickerDetails( + string _ticker, + address _owner, + uint256 _registrationDate, + uint256 _expiryDate, + string _tokenName, + bool _status + ) internal { + bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); + if (getAddress(key) != _owner) + set(key, _owner); + key = Encoder.getKey("registeredTickers_registrationDate", _ticker); + if (getUint(key) != _registrationDate) + set(key, _registrationDate); + key = Encoder.getKey("registeredTickers_expiryDate", _ticker); + if (getUint(key) != _expiryDate) + set(key, _expiryDate); + key = Encoder.getKey("registeredTickers_tokenName", _ticker); + if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) + set(key, _tokenName); + key = Encoder.getKey("registeredTickers_status", _ticker); + if (getBool(key) != _status) + set(key, _status); + } + + +} \ No newline at end of file diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 47e735613..93275c3c1 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -10,11 +10,12 @@ import "./storage/EternalStorage.sol"; import "./libraries/Util.sol"; import "./libraries/Encoder.sol"; import "./libraries/VersionUtils.sol"; +import "./InternalRegistry.sol"; /** * @title Registry contract for issuers to register their tickers and security tokens */ -contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { +contract SecurityTokenRegistry is EternalStorage { /** * @notice state variables @@ -203,6 +204,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(POLYTOKEN, IPolymathRegistry(polymathRegistry).getAddress("PolyToken")); } + function setInternalRegistry(address _internalContract) public onlyOwner { + set(Encoder.getKey("internalContract"), _internalContract); + } + ///////////////////////////// // Token Ticker Management ///////////////////////////// @@ -220,285 +225,287 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); // 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"); + // if (tickerFee > 0) + // require(IERC20(getAddress(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) - address previousOwner = _tickerOwner(ticker); - if (previousOwner != address(0)) { - _deleteTickerOwnership(previousOwner, ticker); - } + // require(_tickerAvailable(ticker), "Ticker is reserved"); + // // Check whether ticker was previously registered (and expired) + // address previousOwner = _tickerOwner(ticker); + // 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); - } - - /** - * @notice Internal - Sets the details of the ticker - */ - function _addTicker( - address _owner, - string _ticker, - string _tokenName, - uint256 _registrationDate, - uint256 _expiryDate, - bool _status, - bool _fromAdmin, - uint256 _fee - ) internal { - _setTickerOwnership(_owner, _ticker); - _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); - } - - /** - * @notice Modifies the ticker details. Only Polymath has the ability to do so. - * @notice Only allowed to modify the tickers which are not yet deployed. - * @param _owner is the owner of the token - * @param _ticker is the token ticker - * @param _tokenName is the name of the token - * @param _registrationDate is the date at which ticker is registered - * @param _expiryDate is the expiry date for the ticker - * @param _status is the token deployment status - */ - function modifyTicker( - address _owner, - string _ticker, - string _tokenName, - uint256 _registrationDate, - uint256 _expiryDate, - bool _status - ) external onlyOwner { - require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); - require(_expiryDate != 0 && _registrationDate != 0, "Dates should not be 0"); - require(_registrationDate <= _expiryDate, "Registration date should < expiry date"); - require(_owner != address(0), "Invalid address"); - string memory ticker = Util.upper(_ticker); - _modifyTicker(_owner, ticker, _tokenName, _registrationDate, _expiryDate, _status); - } - - /** - * @notice Internal -- Modifies the ticker details. - */ - function _modifyTicker( - address _owner, - string _ticker, - string _tokenName, - uint256 _registrationDate, - uint256 _expiryDate, - bool _status - ) internal { - address currentOwner = _tickerOwner(_ticker); - if (currentOwner != address(0)) { - _deleteTickerOwnership(currentOwner, _ticker); - } - if (_tickerStatus(_ticker) && !_status) { - set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); - } - // 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"); - } - _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0)); - } + bytes4 funcId = InternalRegistry(getAddress("internalContract")).addTicker.selector; + require(getAddress("internalContract").delegatecall.gas(500000)(funcId, _owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, tickerFee)); + //_addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, tickerFee); + } + +// /** +// * @notice Internal - Sets the details of the ticker +// */ +// function _addTicker( +// address _owner, +// string _ticker, +// string _tokenName, +// uint256 _registrationDate, +// uint256 _expiryDate, +// bool _status, +// bool _fromAdmin, +// uint256 _fee +// ) internal { +// _setTickerOwnership(_owner, _ticker); +// _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); +// emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); +// } + +// /** +// * @notice Modifies the ticker details. Only Polymath has the ability to do so. +// * @notice Only allowed to modify the tickers which are not yet deployed. +// * @param _owner is the owner of the token +// * @param _ticker is the token ticker +// * @param _tokenName is the name of the token +// * @param _registrationDate is the date at which ticker is registered +// * @param _expiryDate is the expiry date for the ticker +// * @param _status is the token deployment status +// */ +// function modifyTicker( +// address _owner, +// string _ticker, +// string _tokenName, +// uint256 _registrationDate, +// uint256 _expiryDate, +// bool _status +// ) external onlyOwner { +// require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); +// require(_expiryDate != 0 && _registrationDate != 0, "Dates should not be 0"); +// require(_registrationDate <= _expiryDate, "Registration date should < expiry date"); +// require(_owner != address(0), "Invalid address"); +// string memory ticker = Util.upper(_ticker); +// _modifyTicker(_owner, ticker, _tokenName, _registrationDate, _expiryDate, _status); +// } + +// /** +// * @notice Internal -- Modifies the ticker details. +// */ +// function _modifyTicker( +// address _owner, +// string _ticker, +// string _tokenName, +// uint256 _registrationDate, +// uint256 _expiryDate, +// bool _status +// ) internal { +// address currentOwner = _tickerOwner(_ticker); +// if (currentOwner != address(0)) { +// _deleteTickerOwnership(currentOwner, _ticker); +// } +// if (_tickerStatus(_ticker) && !_status) { +// set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); +// } +// // 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"); +// } +// _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)); } - /** - * @notice Removes the ticker details, associated ownership & security token mapping - * @param _ticker is the token ticker - */ - function removeTicker(string _ticker) external onlyOwner { - string memory ticker = Util.upper(_ticker); - address owner = _tickerOwner(ticker); - require(owner != address(0), "Ticker doesn't exist"); - _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); - } - - /** - * @notice Internal - Checks if the entered ticker is registered and has not expired - * @param _ticker is the token ticker - * @return bool - */ - 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 - return false; - } - return true; - } +// /** +// * @notice Removes the ticker details, associated ownership & security token mapping +// * @param _ticker is the token ticker +// */ +// function removeTicker(string _ticker) external onlyOwner { +// string memory ticker = Util.upper(_ticker); +// address owner = _tickerOwner(ticker); +// require(owner != address(0), "Ticker doesn't exist"); +// _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); +// } + +// /** +// * @notice Internal - Checks if the entered ticker is registered and has not expired +// * @param _ticker is the token ticker +// * @return bool +// */ +// 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 +// return false; +// } +// return true; +// } function _tickerStatus(string _ticker) internal view returns(bool) { return getBool(Encoder.getKey("registeredTickers_status", _ticker)); } - /** - * @notice Internal - Sets the ticker owner - * @param _owner is the address of the owner of the ticker - * @param _ticker is the ticker symbol - */ - function _setTickerOwnership(address _owner, string _ticker) internal { - bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); - uint256 length = uint256(getArrayBytes32(_ownerKey).length); - pushArray(_ownerKey, Util.stringToBytes32(_ticker)); - set(Encoder.getKey("tickerIndex", _ticker), length); - bytes32 seenKey = Encoder.getKey("seenUsers", _owner); - if (!getBool(seenKey)) { - pushArray(Encoder.getKey("activeUsers"), _owner); - set(seenKey, true); - } - } - - /** - * @notice Internal - Stores the ticker details - */ - function _storeTickerDetails( - string _ticker, - address _owner, - uint256 _registrationDate, - uint256 _expiryDate, - string _tokenName, - bool _status - ) internal { - bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); - if (getAddress(key) != _owner) - set(key, _owner); - key = Encoder.getKey("registeredTickers_registrationDate", _ticker); - if (getUint(key) != _registrationDate) - set(key, _registrationDate); - key = Encoder.getKey("registeredTickers_expiryDate", _ticker); - if (getUint(key) != _expiryDate) - set(key, _expiryDate); - key = Encoder.getKey("registeredTickers_tokenName", _ticker); - if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) - set(key, _tokenName); - key = Encoder.getKey("registeredTickers_status", _ticker); - if (getBool(key) != _status) - set(key, _status); - } - - /** - * @notice Transfers the ownership of the ticker - * @param _newOwner is the address of the new owner of the ticker - * @param _ticker is the ticker symbol - */ - function transferTickerOwnership(address _newOwner, string _ticker) external whenNotPausedOrOwner { - 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"); - if (_tickerStatus(ticker)) - require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); - _deleteTickerOwnership(msg.sender, ticker); - _setTickerOwnership(_newOwner, ticker); - set(ownerKey, _newOwner); - emit ChangeTickerOwnership(ticker, msg.sender, _newOwner); - } - - /** - * @notice Internal - Removes the owner of a ticker - */ - function _deleteTickerOwnership(address _owner, string _ticker) internal { - uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); - bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); - bytes32[] memory tickers = getArrayBytes32(ownerKey); - assert(index < tickers.length); - assert(_tickerOwner(_ticker) == _owner); - deleteArrayBytes32(ownerKey, index); - if (getArrayBytes32(ownerKey).length > index) { - bytes32 switchedTicker = getArrayBytes32(ownerKey)[index]; - set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); - } - } - - /** - * @notice Changes the expiry time for the token ticker. Only available to Polymath. - * @param _newExpiry is the new expiry for newly generated tickers - */ - function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { - require(_newExpiry >= 1 days, "Expiry should >= 1 day"); - emit ChangeExpiryLimit(getUint(EXPIRYLIMIT), _newExpiry); - set(EXPIRYLIMIT, _newExpiry); - } - - /** - * @notice Returns the list of tickers owned by the selected address - * @param _owner is the address which owns the list of tickers - */ - function getTickersByOwner(address _owner) external view returns(bytes32[]) { - uint counter = 0; - // accessing the data structure userTotickers[_owner].length - bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); - 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)) { - counter ++; - } - } - bytes32[] memory tempList = new bytes32[](counter); - counter = 0; - 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)) { - tempList[counter] = tickers[i]; - counter ++; - } - } - return tempList; - } - - /** - * @notice Returns the list of tokens owned by the selected address - * @param _owner is the address which owns the list of tickers - * @dev Intention is that this is called off-chain so block gas limit is not relevant - */ - function getTokensByOwner(address _owner) external view returns(address[]) { - // Loop over all active users, then all associated tickers of those users - // This ensures we find tokens, even if their owner has been modified - address[] memory activeUsers = getArrayAddress(Encoder.getKey("activeUsers")); - bytes32[] memory tickers; - address token; - uint256 count = 0; - uint256 i = 0; - uint256 j = 0; - 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]))); - if (token != address(0)) { - if (IOwnable(token).owner() == _owner) { - count = count + 1; - } - } - } - } - uint256 index = 0; - address[] memory result = new address[](count); - 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]))); - if (token != address(0)) { - if (IOwnable(token).owner() == _owner) { - result[index] = token; - index = index + 1; - } - } - } - } - return result; - } +// /** +// * @notice Internal - Sets the ticker owner +// * @param _owner is the address of the owner of the ticker +// * @param _ticker is the ticker symbol +// */ +// function _setTickerOwnership(address _owner, string _ticker) internal { +// bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); +// uint256 length = uint256(getArrayBytes32(_ownerKey).length); +// pushArray(_ownerKey, Util.stringToBytes32(_ticker)); +// set(Encoder.getKey("tickerIndex", _ticker), length); +// bytes32 seenKey = Encoder.getKey("seenUsers", _owner); +// if (!getBool(seenKey)) { +// pushArray(Encoder.getKey("activeUsers"), _owner); +// set(seenKey, true); +// } +// } + +// /** +// * @notice Internal - Stores the ticker details +// */ +// function _storeTickerDetails( +// string _ticker, +// address _owner, +// uint256 _registrationDate, +// uint256 _expiryDate, +// string _tokenName, +// bool _status +// ) internal { +// bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); +// if (getAddress(key) != _owner) +// set(key, _owner); +// key = Encoder.getKey("registeredTickers_registrationDate", _ticker); +// if (getUint(key) != _registrationDate) +// set(key, _registrationDate); +// key = Encoder.getKey("registeredTickers_expiryDate", _ticker); +// if (getUint(key) != _expiryDate) +// set(key, _expiryDate); +// key = Encoder.getKey("registeredTickers_tokenName", _ticker); +// if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) +// set(key, _tokenName); +// key = Encoder.getKey("registeredTickers_status", _ticker); +// if (getBool(key) != _status) +// set(key, _status); +// } + +// /** +// * @notice Transfers the ownership of the ticker +// * @param _newOwner is the address of the new owner of the ticker +// * @param _ticker is the ticker symbol +// */ +// function transferTickerOwnership(address _newOwner, string _ticker) external whenNotPausedOrOwner { +// 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"); +// if (_tickerStatus(ticker)) +// require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); +// _deleteTickerOwnership(msg.sender, ticker); +// _setTickerOwnership(_newOwner, ticker); +// set(ownerKey, _newOwner); +// emit ChangeTickerOwnership(ticker, msg.sender, _newOwner); +// } + +// /** +// * @notice Internal - Removes the owner of a ticker +// */ +// function _deleteTickerOwnership(address _owner, string _ticker) internal { +// uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); +// bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); +// bytes32[] memory tickers = getArrayBytes32(ownerKey); +// assert(index < tickers.length); +// assert(_tickerOwner(_ticker) == _owner); +// deleteArrayBytes32(ownerKey, index); +// if (getArrayBytes32(ownerKey).length > index) { +// bytes32 switchedTicker = getArrayBytes32(ownerKey)[index]; +// set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); +// } +// } + +// /** +// * @notice Changes the expiry time for the token ticker. Only available to Polymath. +// * @param _newExpiry is the new expiry for newly generated tickers +// */ +// function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { +// require(_newExpiry >= 1 days, "Expiry should >= 1 day"); +// emit ChangeExpiryLimit(getUint(EXPIRYLIMIT), _newExpiry); +// set(EXPIRYLIMIT, _newExpiry); +// } + +// /** +// * @notice Returns the list of tickers owned by the selected address +// * @param _owner is the address which owns the list of tickers +// */ +// function getTickersByOwner(address _owner) external view returns(bytes32[]) { +// uint counter = 0; +// // accessing the data structure userTotickers[_owner].length +// bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); +// 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)) { +// counter ++; +// } +// } +// bytes32[] memory tempList = new bytes32[](counter); +// counter = 0; +// 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)) { +// tempList[counter] = tickers[i]; +// counter ++; +// } +// } +// return tempList; +// } + +// /** +// * @notice Returns the list of tokens owned by the selected address +// * @param _owner is the address which owns the list of tickers +// * @dev Intention is that this is called off-chain so block gas limit is not relevant +// */ +// function getTokensByOwner(address _owner) external view returns(address[]) { +// // Loop over all active users, then all associated tickers of those users +// // This ensures we find tokens, even if their owner has been modified +// address[] memory activeUsers = getArrayAddress(Encoder.getKey("activeUsers")); +// bytes32[] memory tickers; +// address token; +// uint256 count = 0; +// uint256 i = 0; +// uint256 j = 0; +// 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]))); +// if (token != address(0)) { +// if (IOwnable(token).owner() == _owner) { +// count = count + 1; +// } +// } +// } +// } +// uint256 index = 0; +// address[] memory result = new address[](count); +// 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]))); +// if (token != address(0)) { +// if (IOwnable(token).owner() == _owner) { +// result[index] = token; +// index = index + 1; +// } +// } +// } +// } +// return result; +// } /** * @notice Returns the owner and timestamp for a given ticker @@ -527,209 +534,209 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return (address(0), uint256(0), uint256(0), "", false); } - ///////////////////////////// - // Security Token Management - ///////////////////////////// - - /** - * @notice Deploys an instance of a new Security Token and records it to the registry - * @param _name is the name of the token - * @param _ticker is the ticker symbol of the security token - * @param _tokenDetails is the off-chain details of the token - * @param _divisible is whether or not the token is divisible - */ - function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external whenNotPausedOrOwner { - 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"); - 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(); - if (launchFee > 0) - require(IERC20(getAddress(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); - - address newSecurityTokenAddress = ISTFactory(getSTFactoryAddress()).deployToken( - _name, - ticker, - 18, - _tokenDetails, - msg.sender, - _divisible, - 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); - } - - /** - * @notice Adds a new custom Security Token and saves it to the registry. (Token should follow the ISecurityToken interface) - * @param _name is the name of the token - * @param _ticker is the ticker symbol of the security token - * @param _owner is the owner of the token - * @param _securityToken is the address of the securityToken - * @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 - { - 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"); - 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)); - if (registrationTime == 0) { - /*solium-disable-next-line security/no-block-members*/ - registrationTime = now; - expiryTime = registrationTime.add(getExpiryLimit()); - } - set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); - _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); - _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); - emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getSecurityTokenLaunchFee()); - } - - /** - * @notice Internal - Stores the security token details - */ - function _storeSecurityTokenData(address _securityToken, string _ticker, string _tokenDetails, uint256 _deployedAt) internal { - set(Encoder.getKey("securityTokens_ticker", _securityToken), _ticker); - set(Encoder.getKey("securityTokens_tokenDetails", _securityToken), _tokenDetails); - set(Encoder.getKey("securityTokens_deployedAt", _securityToken), _deployedAt); - } - - /** - * @notice Checks that Security Token is registered - * @param _securityToken is the address of the security token - * @return bool - */ - function isSecurityToken(address _securityToken) external view returns (bool) { - return (keccak256(bytes(getString(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); - } - - /** - * @notice Returns the security token address by ticker symbol - * @param _ticker is the ticker of the security token - * @return address - */ - function getSecurityTokenAddress(string _ticker) external view returns (address) { - string memory ticker = Util.upper(_ticker); - return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); - } - - /** - * @notice Returns the security token data by address - * @param _securityToken is the address of the security token. - * @return string is the ticker of the security Token. - * @return address is the issuer of the security Token. - * @return string is the details of the security token. - * @return uint256 is the timestamp at which security Token was deployed. - */ - function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256) { - return ( - getString(Encoder.getKey("securityTokens_ticker", _securityToken)), - IOwnable(_securityToken).owner(), - getString(Encoder.getKey("securityTokens_tokenDetails", _securityToken)), - getUint(Encoder.getKey("securityTokens_deployedAt", _securityToken)) - ); - } - - ///////////////////////////// - // Ownership, lifecycle & Utility - ///////////////////////////// - - /** - * @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 onlyOwner { - require(_newOwner != address(0), "Invalid address"); - emit OwnershipTransferred(getAddress(OWNER), _newOwner); - set(OWNER, _newOwner); - } - - /** - * @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 - */ - function unpause() external whenPaused onlyOwner { - set(PAUSED, false); - /*solium-disable-next-line security/no-block-members*/ - emit Unpause(now); - } - - /** - * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. - * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) - */ - function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { - uint256 fee = getUint(TICKERREGFEE); - require(fee != _tickerRegFee, "Fee not changed"); - emit ChangeTickerRegistrationFee(fee, _tickerRegFee); - set(TICKERREGFEE, _tickerRegFee); - } - - /** - * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. - * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) - */ - function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { - uint256 fee = getUint(STLAUNCHFEE); - require(fee != _stLaunchFee, "Fee not changed"); - emit ChangeSecurityLaunchFee(fee, _stLaunchFee); - set(STLAUNCHFEE, _stLaunchFee); - } - - /** - * @notice Reclaims all ERC20Basic compatible tokens - * @param _tokenContract is 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(owner(), balance), "Transfer failed"); - } - - /** - * @notice Changes the protocol version and the SecurityToken contract - * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions - * @notice Changing versions does not affect existing tokens. - * @param _STFactoryAddress is the address of the proxy. - * @param _major Major version of the proxy. - * @param _minor Minor version of the proxy. - * @param _patch Patch version of the proxy - */ - function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { - require(_STFactoryAddress != address(0), "0x address is not allowed"); - _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); - } +// ///////////////////////////// +// // Security Token Management +// ///////////////////////////// + +// /** +// * @notice Deploys an instance of a new Security Token and records it to the registry +// * @param _name is the name of the token +// * @param _ticker is the ticker symbol of the security token +// * @param _tokenDetails is the off-chain details of the token +// * @param _divisible is whether or not the token is divisible +// */ +// function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external whenNotPausedOrOwner { +// 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"); +// 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(); +// if (launchFee > 0) +// require(IERC20(getAddress(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); + +// address newSecurityTokenAddress = ISTFactory(getSTFactoryAddress()).deployToken( +// _name, +// ticker, +// 18, +// _tokenDetails, +// msg.sender, +// _divisible, +// 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); +// } + +// /** +// * @notice Adds a new custom Security Token and saves it to the registry. (Token should follow the ISecurityToken interface) +// * @param _name is the name of the token +// * @param _ticker is the ticker symbol of the security token +// * @param _owner is the owner of the token +// * @param _securityToken is the address of the securityToken +// * @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 +// { +// 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"); +// 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)); +// if (registrationTime == 0) { +// /*solium-disable-next-line security/no-block-members*/ +// registrationTime = now; +// expiryTime = registrationTime.add(getExpiryLimit()); +// } +// set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); +// _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); +// _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); +// emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getSecurityTokenLaunchFee()); +// } + +// /** +// * @notice Internal - Stores the security token details +// */ +// function _storeSecurityTokenData(address _securityToken, string _ticker, string _tokenDetails, uint256 _deployedAt) internal { +// set(Encoder.getKey("securityTokens_ticker", _securityToken), _ticker); +// set(Encoder.getKey("securityTokens_tokenDetails", _securityToken), _tokenDetails); +// set(Encoder.getKey("securityTokens_deployedAt", _securityToken), _deployedAt); +// } + +// /** +// * @notice Checks that Security Token is registered +// * @param _securityToken is the address of the security token +// * @return bool +// */ +// function isSecurityToken(address _securityToken) external view returns (bool) { +// return (keccak256(bytes(getString(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); +// } + +// /** +// * @notice Returns the security token address by ticker symbol +// * @param _ticker is the ticker of the security token +// * @return address +// */ +// function getSecurityTokenAddress(string _ticker) external view returns (address) { +// string memory ticker = Util.upper(_ticker); +// return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); +// } + +// /** +// * @notice Returns the security token data by address +// * @param _securityToken is the address of the security token. +// * @return string is the ticker of the security Token. +// * @return address is the issuer of the security Token. +// * @return string is the details of the security token. +// * @return uint256 is the timestamp at which security Token was deployed. +// */ +// function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256) { +// return ( +// getString(Encoder.getKey("securityTokens_ticker", _securityToken)), +// IOwnable(_securityToken).owner(), +// getString(Encoder.getKey("securityTokens_tokenDetails", _securityToken)), +// getUint(Encoder.getKey("securityTokens_deployedAt", _securityToken)) +// ); +// } + +// ///////////////////////////// +// // Ownership, lifecycle & Utility +// ///////////////////////////// + +// /** +// * @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 onlyOwner { +// require(_newOwner != address(0), "Invalid address"); +// emit OwnershipTransferred(getAddress(OWNER), _newOwner); +// set(OWNER, _newOwner); +// } + +// /** +// * @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 +// */ +// function unpause() external whenPaused onlyOwner { +// set(PAUSED, false); +// /*solium-disable-next-line security/no-block-members*/ +// emit Unpause(now); +// } + +// /** +// * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. +// * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) +// */ +// function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { +// uint256 fee = getUint(TICKERREGFEE); +// require(fee != _tickerRegFee, "Fee not changed"); +// emit ChangeTickerRegistrationFee(fee, _tickerRegFee); +// set(TICKERREGFEE, _tickerRegFee); +// } + +// /** +// * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. +// * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) +// */ +// function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { +// uint256 fee = getUint(STLAUNCHFEE); +// require(fee != _stLaunchFee, "Fee not changed"); +// emit ChangeSecurityLaunchFee(fee, _stLaunchFee); +// set(STLAUNCHFEE, _stLaunchFee); +// } + +// /** +// * @notice Reclaims all ERC20Basic compatible tokens +// * @param _tokenContract is 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(owner(), balance), "Transfer failed"); +// } + +// /** +// * @notice Changes the protocol version and the SecurityToken contract +// * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions +// * @notice Changing versions does not affect existing tokens. +// * @param _STFactoryAddress is the address of the proxy. +// * @param _major Major version of the proxy. +// * @param _minor Minor version of the proxy. +// * @param _patch Patch version of the proxy +// */ +// function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { +// require(_STFactoryAddress != address(0), "0x address is not allowed"); +// _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); +// } /** * @notice Internal - Changes the protocol version and the SecurityToken contract @@ -745,12 +752,12 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("protocolVersionST", getUint(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")))); - } +// /** +// * @notice Returns the current STFactory Address +// */ +// function getSTFactoryAddress() public view returns(address) { +// return getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion")))); +// } /** * @notice Gets Protocol version diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 4a28d2d67..5b49044fa 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -27,6 +27,7 @@ const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') const MockOracle = artifacts.require('./MockOracle.sol') const TokenLib = artifacts.require('./TokenLib.sol'); const SecurityToken = artifacts.require('./tokens/SecurityToken.sol') +const InternalRegistry = artifacts.require('./InternalRegistry.sol'); let BigNumber = require('bignumber.js'); const cappedSTOSetupCost = new BigNumber(20000).times(new BigNumber(10).pow(18)); // 20K POLY fee @@ -232,6 +233,8 @@ module.exports = function (deployer, network, accounts) { }).then(() => { let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolymathAccount]); return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); + }).then(() => { + return deployer.deploy(InternalRegistry, {from: PolymathAccount}); }).then(() => { // Assign the address into the SecurityTokenRegistry key return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); @@ -339,6 +342,7 @@ module.exports = function (deployer, network, accounts) { SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} ModuleRegistry (Proxy): ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} + InternalRegsitry: ${InternalRegistry.address} ETHOracle: ${ETHOracle} POLYOracle: ${POLYOracle} diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index cc2b1fdca..0383e2fc3 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -11,6 +11,7 @@ const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryPro const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); const STFactory = artifacts.require("./STFactory.sol"); +const InternalRegistry = artifacts.require('./InternalRegistry.sol'); const Web3 = require("web3"); @@ -59,6 +60,7 @@ contract("SecurityTokenRegistry", accounts => { let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; + let I_InternalRegistry; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -332,66 +334,72 @@ contract("SecurityTokenRegistry", accounts => { 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 register the ticker when the tickerRegFee is 0", async() => { - let snap_Id = await takeSnapshot(); - await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); - let tx = await I_STRProxied.registerTicker(account_temp, "ZERO", 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, "ZERO", `Symbol should be ZERO`); - await revertToSnapshot(snap_Id); - }) - - it("Should fail to register same symbol again", async () => { - // Give POLY to token issuer - await I_PolyToken.getTokens(initRegFee, token_owner); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - // Call registration function - catchRevert( - I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }), - "tx revert -> Symbol is already alloted to someone else" - ); - }); - - 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 () => { - await I_STRProxied.pause({ from: account_polymath }); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - - catchRevert( - I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }), - "tx revert -> Registration is paused" - ); - }); - - it("Should fail to pause if already paused", async () => { - catchRevert(I_STRProxied.pause({ from: account_polymath }), "tx revert -> Registration is already paused"); - }); - - 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 () => { - catchRevert(I_STRProxied.unpause({ from: account_polymath }), "tx revert -> Registration is already unpaused"); - }); + console.log(tx); + // 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}`); + console.log(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("internalContract"))); + console.log(I_InternalRegistry.address); + console.log(await I_STRProxied.getTickerDetails.call(symbol)); + console.log(await I_InternalRegistry.getUintValues.call(web3.utils.soliditySha3("registeredTickers_expiryDate",symbol))); + console.log(await I_SecurityTokenRegistry.getTickerDetails.call(symbol)); + }); + + // it("Should register the ticker when the tickerRegFee is 0", async() => { + // let snap_Id = await takeSnapshot(); + // await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); + // let tx = await I_STRProxied.registerTicker(account_temp, "ZERO", 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, "ZERO", `Symbol should be ZERO`); + // await revertToSnapshot(snap_Id); + // }) + + // it("Should fail to register same symbol again", async () => { + // // Give POLY to token issuer + // await I_PolyToken.getTokens(initRegFee, token_owner); + // await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + // // Call registration function + // catchRevert( + // I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }), + // "tx revert -> Symbol is already alloted to someone else" + // ); + // }); + + // 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 () => { + // await I_STRProxied.pause({ from: account_polymath }); + // await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + + // catchRevert( + // I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }), + // "tx revert -> Registration is paused" + // ); + // }); + + // it("Should fail to pause if already paused", async () => { + // catchRevert(I_STRProxied.pause({ from: account_polymath }), "tx revert -> Registration is already paused"); + // }); + + // 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 () => { + // catchRevert(I_STRProxied.unpause({ from: account_polymath }), "tx revert -> Registration is already unpaused"); + // }); }); - describe("Test cases for the expiry limit", async () => { + describe.skip("Test cases for the expiry limit", async () => { it("Should fail to set the expiry limit because msg.sender is not owner", async () => { catchRevert(I_STRProxied.changeExpiryLimit(duration.days(10), { from: account_temp }), "tx revert -> msg.sender is not owner"); }); @@ -413,7 +421,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Test cases for the getTickerDetails", async () => { + describe.skip("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"); @@ -429,7 +437,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Generate SecurityToken", async () => { + describe.skip("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"); @@ -527,7 +535,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Generate SecurityToken v2", async () => { + describe.skip("Generate SecurityToken v2", async () => { it("Should deploy the st version 2", async () => { // Step 7: Deploy the STFactory contract @@ -572,7 +580,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Deploy the new SecurityTokenRegistry", async () => { + describe.skip("Deploy the new SecurityTokenRegistry", async () => { it("Should deploy the new SecurityTokenRegistry contract logic", async () => { I_SecurityTokenRegistryV2 = await SecurityTokenRegistryMock.new({ from: account_polymath }); assert.notEqual( @@ -610,7 +618,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Generate custom tokens", async () => { + describe.skip("Generate custom tokens", async () => { it("Should fail if msg.sender is not polymath", async () => { catchRevert( I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), { @@ -1043,102 +1051,102 @@ contract("SecurityTokenRegistry", accounts => { describe("Test cases for IRegistry functionality", async () => { describe("Test cases for reclaiming funds", async () => { - it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { - I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); - catchRevert( - I_STRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) - ); - }); - - it("Should successfully reclaim POLY tokens -- not authorised", async() => { - catchRevert( - I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) - ); - }); - - it("Should successfully reclaim POLY tokens", async () => { - let bal1 = await I_PolyToken.balanceOf.call(account_polymath); - await I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_polymath }); - 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 () => { - catchRevert(I_STRProxied.pause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); - }); - - 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 () => { - catchRevert(I_STRProxied.unpause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); - }); - - 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); - }); - }); - - describe("Test cases for the setProtocolVersion", async() => { - - it("Should successfully change the protocolVersion -- failed because of bad owner", async() => { - catchRevert( - I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp }) - ); - }); + // it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { + // I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); + // catchRevert( + // I_STRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) + // ); + // }); + + // it("Should successfully reclaim POLY tokens -- not authorised", async() => { + // catchRevert( + // I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) + // ); + // }); + + // it("Should successfully reclaim POLY tokens", async () => { + // let bal1 = await I_PolyToken.balanceOf.call(account_polymath); + // await I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_polymath }); + // 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 () => { + // catchRevert(I_STRProxied.pause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); + // }); + + // 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 () => { + // catchRevert(I_STRProxied.unpause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); + // }); + + // 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); + // }); + // }); + + // describe("Test cases for the setProtocolVersion", async() => { + + // it("Should successfully change the protocolVersion -- failed because of bad owner", async() => { + // catchRevert( + // I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp }) + // ); + // }); - it("Should successfully change the protocolVersion -- failed because factory address is 0x", async() => { - catchRevert( - I_STRProxied.setProtocolVersion("0x000000000000000000000000000000000000000", 5, 6, 7, { from: account_polymath }) - ); - }); + // it("Should successfully change the protocolVersion -- failed because factory address is 0x", async() => { + // catchRevert( + // I_STRProxied.setProtocolVersion("0x000000000000000000000000000000000000000", 5, 6, 7, { from: account_polymath }) + // ); + // }); - it("Should successfully change the protocolVersion -- not a valid vesrion", async() => { - catchRevert( - I_STRProxied.setProtocolVersion(accounts[8], 0, 0, 0, { from: account_polymath }) - ); - }); - - it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async() => { - let snap_Id = await takeSnapshot(); - await I_STRProxied.setProtocolVersion(accounts[8], 2, 3, 1, {from: account_polymath }); - await catchRevert( - I_STRProxied.setProtocolVersion(accounts[8], 1, 3, 1, {from: account_polymath }) - ); - await revertToSnapshot(snap_Id); - }); + // it("Should successfully change the protocolVersion -- not a valid vesrion", async() => { + // catchRevert( + // I_STRProxied.setProtocolVersion(accounts[8], 0, 0, 0, { from: account_polymath }) + // ); + // }); + + // it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async() => { + // let snap_Id = await takeSnapshot(); + // await I_STRProxied.setProtocolVersion(accounts[8], 2, 3, 1, {from: account_polymath }); + // await catchRevert( + // I_STRProxied.setProtocolVersion(accounts[8], 1, 3, 1, {from: account_polymath }) + // ); + // await revertToSnapshot(snap_Id); + // }); - }); - - describe("Test cases for the transferOwnership", async() => { - - it("Should fail to transfer the ownership -- not authorised", async() => { - catchRevert( - I_STRProxied.transferOwnership(account_temp, { from: account_issuer}) - ); - }); - - it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { - catchRevert( - I_STRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) - ); - }); - - it("Should successfully transfer the ownership of the STR", async() => { - let tx = await I_STRProxied.transferOwnership(account_temp, { from: account_polymath }); - assert.equal(tx.logs[0].args.previousOwner, account_polymath); - assert.equal(tx.logs[0].args.newOwner, account_temp); - }); - }) - }); + // }); + + // describe("Test cases for the transferOwnership", async() => { + + // it("Should fail to transfer the ownership -- not authorised", async() => { + // catchRevert( + // I_STRProxied.transferOwnership(account_temp, { from: account_issuer}) + // ); + // }); + + // it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { + // catchRevert( + // I_STRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) + // ); + // }); + + // it("Should successfully transfer the ownership of the STR", async() => { + // let tx = await I_STRProxied.transferOwnership(account_temp, { from: account_polymath }); + // assert.equal(tx.logs[0].args.previousOwner, account_polymath); + // assert.equal(tx.logs[0].args.newOwner, account_temp); + // }); + // }) + //}); }); From a287d34cd6c80b9458c64498da862b482e3d37b1 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 2 Jan 2019 18:05:55 +0530 Subject: [PATCH 049/119] upgrade tests --- CHANGELOG.md | 2 + contracts/InternalRegistry.sol | 86 -- contracts/STRGetter.sol | 196 ++++ contracts/SecurityTokenRegistry.sol | 943 ++++++++---------- migrations/2_deploy_contracts.js | 13 +- test/b_capped_sto.js | 4 +- test/c_checkpoints.js | 4 +- test/d_count_transfer_manager.js | 4 +- test/e_erc20_dividends.js | 4 +- test/f_ether_dividends.js | 4 +- test/g_general_permission_manager.js | 4 +- test/h_general_transfer_manager.js | 4 +- test/helpers/createInstances.js | 11 +- test/i_Issuance.js | 4 +- test/j_manual_approval_transfer_manager.js | 4 +- test/k_module_registry.js | 4 +- test/l_percentage_transfer_manager.js | 6 +- test/m_presale_sto.js | 4 +- test/n_security_token_registry.js | 508 +++++----- test/o_security_token.js | 4 +- test/p_usd_tiered_sto.js | 4 +- test/q_usd_tiered_sto_sim.js | 4 +- test/r_concurrent_STO.js | 4 +- test/s_v130_to_v140_upgrade.js | 4 +- test/t_security_token_registry_proxy.js | 19 +- test/u_module_registry_proxy.js | 4 +- test/v_tracked_redemptions.js | 4 +- ...kup_volume_restriction_transfer_manager.js | 4 +- test/y_scheduled_checkpoints.js | 4 +- test/z_general_permission_manager_fuzzer.js | 4 +- yarn.lock | 2 +- 31 files changed, 964 insertions(+), 906 deletions(-) delete mode 100644 contracts/InternalRegistry.sol create mode 100644 contracts/STRGetter.sol diff --git a/CHANGELOG.md b/CHANGELOG.md index cbc665fb4..edd733dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,14 @@ All notable changes to this project will be documented in this file. ## Added * Added new function `addModuleWithLabel()` which takes an extra param `_label` that used for giving the customize label to the module for display purpose. #428 +* Introduce new contract `STRGetter.sol`. It only contains the getter functions of the STR. ## Fixed * Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. * Fixed event `ModuleAdded` to also emit `_label`. * Fixed function `getModule` to also return the respective module label. * Replaced `updatePolyTokenAddress()` function with `updateFromRegistry()` in `SecurityTokenRegistry`. +* Migrate all the getters of `SecurityTokenRegsitry.sol` to `STRGetter.sol` contract. ## Removed * Removed `_polyAddress` parameter from constructors of all modules and module factories. diff --git a/contracts/InternalRegistry.sol b/contracts/InternalRegistry.sol deleted file mode 100644 index ff60e8ffb..000000000 --- a/contracts/InternalRegistry.sol +++ /dev/null @@ -1,86 +0,0 @@ -pragma solidity ^0.4.24; - -import "./storage/EternalStorage.sol"; -import "./libraries/Util.sol"; -import "./libraries/Encoder.sol"; - -contract InternalRegistry is EternalStorage { - - // Emit after ticker registration - event RegisterTicker( - address indexed _owner, - string _ticker, - string _name, - uint256 indexed _registrationDate, - uint256 indexed _expiryDate, - bool _fromAdmin, - uint256 _registrationFee - ); - - /** - * @notice Internal - Sets the details of the ticker - */ - function addTicker( - address _owner, - string _ticker, - string _tokenName, - uint256 _registrationDate, - uint256 _expiryDate, - bool _status, - bool _fromAdmin, - uint256 _fee - ) - public - { - _setTickerOwnership(_owner, _ticker); - _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); - } - - /** - * @notice Internal - Sets the ticker owner - * @param _owner is the address of the owner of the ticker - * @param _ticker is the ticker symbol - */ - function _setTickerOwnership(address _owner, string _ticker) internal { - bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); - uint256 length = uint256(getArrayBytes32(_ownerKey).length); - pushArray(_ownerKey, Util.stringToBytes32(_ticker)); - set(Encoder.getKey("tickerIndex", _ticker), length); - bytes32 seenKey = Encoder.getKey("seenUsers", _owner); - if (!getBool(seenKey)) { - pushArray(Encoder.getKey("activeUsers"), _owner); - set(seenKey, true); - } - } - - /** - * @notice Internal - Stores the ticker details - */ - function _storeTickerDetails( - string _ticker, - address _owner, - uint256 _registrationDate, - uint256 _expiryDate, - string _tokenName, - bool _status - ) internal { - bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); - if (getAddress(key) != _owner) - set(key, _owner); - key = Encoder.getKey("registeredTickers_registrationDate", _ticker); - if (getUint(key) != _registrationDate) - set(key, _registrationDate); - key = Encoder.getKey("registeredTickers_expiryDate", _ticker); - if (getUint(key) != _expiryDate) - set(key, _expiryDate); - key = Encoder.getKey("registeredTickers_tokenName", _ticker); - if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) - set(key, _tokenName); - key = Encoder.getKey("registeredTickers_status", _ticker); - if (getBool(key) != _status) - set(key, _status); - } - - -} \ No newline at end of file diff --git a/contracts/STRGetter.sol b/contracts/STRGetter.sol new file mode 100644 index 000000000..4187e8eb7 --- /dev/null +++ b/contracts/STRGetter.sol @@ -0,0 +1,196 @@ +pragma solidity ^0.4.24; + +import "./storage/EternalStorage.sol"; +import "./libraries/Util.sol"; +import "./libraries/Encoder.sol"; +import "./interfaces/IOwnable.sol"; +import "./libraries/VersionUtils.sol"; + +contract STRGetter is EternalStorage { + + bytes32 constant STLAUNCHFEE = 0xd677304bb45536bb7fdfa6b9e47a3c58fe413f9e8f01474b0a4b9c6e0275baf2; + bytes32 constant TICKERREGFEE = 0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2; + bytes32 constant EXPIRYLIMIT = 0x604268e9a73dfd777dcecb8a614493dd65c638bad2f5e7d709d378bd2fb0baee; + + /** + * @notice Returns the list of tickers owned by the selected address + * @param _owner is the address which owns the list of tickers + */ + function getTickersByOwner(address _owner) external view returns(bytes32[]) { + uint counter = 0; + // accessing the data structure userTotickers[_owner].length + bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); + 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 || getTickerStatus(ticker)) { + counter ++; + } + } + bytes32[] memory tempList = new bytes32[](counter); + counter = 0; + 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 || getTickerStatus(ticker)) { + tempList[counter] = tickers[i]; + counter ++; + } + } + return tempList; + } + + /** + * @notice Returns the list of tokens owned by the selected address + * @param _owner is the address which owns the list of tickers + * @dev Intention is that this is called off-chain so block gas limit is not relevant + */ + function getTokensByOwner(address _owner) external view returns(address[]) { + // Loop over all active users, then all associated tickers of those users + // This ensures we find tokens, even if their owner has been modified + address[] memory activeUsers = getArrayAddress(Encoder.getKey("activeUsers")); + bytes32[] memory tickers; + address token; + uint256 count = 0; + uint256 i = 0; + uint256 j = 0; + 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]))); + if (token != address(0)) { + if (IOwnable(token).owner() == _owner) { + count = count + 1; + } + } + } + } + uint256 index = 0; + address[] memory result = new address[](count); + 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]))); + if (token != address(0)) { + if (IOwnable(token).owner() == _owner) { + result[index] = token; + index = index + 1; + } + } + } + } + return result; + } + + /** + * @notice Returns the owner and timestamp for a given ticker + * @param _ticker is the ticker symbol + * @return address + * @return uint256 + * @return uint256 + * @return string + * @return bool + */ + function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool) { + string memory ticker = Util.upper(_ticker); + bool tickerStatus = getTickerStatus(ticker); + uint256 expiryDate = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); + /*solium-disable-next-line security/no-block-members*/ + if ((tickerStatus == true) || (expiryDate > now)) { + return + ( + getTickerOwner(ticker), + getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), + expiryDate, + getString(Encoder.getKey("registeredTickers_tokenName", ticker)), + tickerStatus + ); + } else { + return (address(0), uint256(0), uint256(0), "", false); + } + } + + /** + * @notice Returns the security token address by ticker symbol + * @param _ticker is the ticker of the security token + * @return address + */ + function getSecurityTokenAddress(string _ticker) external view returns (address) { + string memory ticker = Util.upper(_ticker); + return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); + } + + /** + * @notice Returns the security token data by address + * @param _securityToken is the address of the security token. + * @return string is the ticker of the security Token. + * @return address is the issuer of the security Token. + * @return string is the details of the security token. + * @return uint256 is the timestamp at which security Token was deployed. + */ + function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256) { + return ( + getString(Encoder.getKey("securityTokens_ticker", _securityToken)), + IOwnable(_securityToken).owner(), + getString(Encoder.getKey("securityTokens_tokenDetails", _securityToken)), + getUint(Encoder.getKey("securityTokens_deployedAt", _securityToken)) + ); + } + + /** + * @notice Returns the current STFactory Address + */ + function getSTFactoryAddress() public view returns(address) { + return getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion")))); + } + + /** + * @notice Gets Protocol version + */ + function getProtocolVersion() public view returns(uint8[]) { + return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); + } + + /** + * @notice Gets the security token launch fee + * @return Fee amount + */ + function getSecurityTokenLaunchFee() public view returns(uint256) { + return getUint(STLAUNCHFEE); + } + + /** + * @notice Gets the ticker registration fee + * @return Fee amount + */ + function getTickerRegistrationFee() public view returns(uint256) { + return getUint(TICKERREGFEE); + } + + /** + * @notice Gets the expiry limit + * @return Expiry limit + */ + function getExpiryLimit() public view returns(uint256) { + return getUint(EXPIRYLIMIT); + } + + /** + * @notice Gets the status of the ticker + * @param _ticker Ticker whose status need to determine + * @return bool + */ + function getTickerStatus(string _ticker) public view returns(bool) { + return getBool(Encoder.getKey("registeredTickers_status", _ticker)); + } + + /** + * @notice Gets the owner of the ticker + * @param _ticker Ticker whose owner need to determine + * @return address Address of the owner + */ + function getTickerOwner(string _ticker) public view returns(address) { + return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + } + +} \ No newline at end of file diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 93275c3c1..9ce1a9cbb 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -10,12 +10,12 @@ import "./storage/EternalStorage.sol"; import "./libraries/Util.sol"; import "./libraries/Encoder.sol"; import "./libraries/VersionUtils.sol"; -import "./InternalRegistry.sol"; +import "./proxy/Proxy.sol"; /** * @title Registry contract for issuers to register their tickers and security tokens */ -contract SecurityTokenRegistry is EternalStorage { +contract SecurityTokenRegistry is EternalStorage, Proxy { /** * @notice state variables @@ -163,21 +163,23 @@ contract SecurityTokenRegistry is EternalStorage { * @param _STFactory is the address of the Proxy contract for Security Tokens * @param _stLaunchFee is the fee in POLY required to launch a token * @param _tickerRegFee is the fee in POLY required to register a ticker - * @param _owner is the owner of the STR + * @param _owner is the owner of the STR, + * @param _getterContract Contract address of the contract which consists getter functions. */ function initialize( address _polymathRegistry, address _STFactory, uint256 _stLaunchFee, uint256 _tickerRegFee, - address _owner + address _owner, + address _getterContract ) external payable { require(!getBool(INITIALIZE),"already initialized"); require( - _STFactory != address(0) && _owner != address(0) && _polymathRegistry != address(0), + _STFactory != address(0) && _owner != address(0) && _polymathRegistry != address(0) && _getterContract != address(0), "Invalid address" ); require(_stLaunchFee != 0 && _tickerRegFee != 0, "Fees should not be 0"); @@ -189,6 +191,7 @@ contract SecurityTokenRegistry is EternalStorage { set(POLYMATHREGISTRY, _polymathRegistry); _setProtocolVersion(_STFactory, uint8(2), uint8(0), uint8(0)); set(INITIALIZE, true); + set(Encoder.getKey("STRGetter"), _getterContract); _updateFromRegistry(); } @@ -204,8 +207,17 @@ contract SecurityTokenRegistry is EternalStorage { set(POLYTOKEN, IPolymathRegistry(polymathRegistry).getAddress("PolyToken")); } - function setInternalRegistry(address _internalContract) public onlyOwner { - set(Encoder.getKey("internalContract"), _internalContract); + /** + * @notice Set the getter contract address + * @param _getterContract Address of the contract + */ + function setGetterRegistry(address _getterContract) public onlyOwner { + require(_getterContract != address(0)); + set(Encoder.getKey("STRGetter"), _getterContract); + } + + function _implementation() internal view returns(address) { + return getAddress(Encoder.getKey("STRGetter")); } ///////////////////////////// @@ -224,570 +236,427 @@ contract SecurityTokenRegistry is EternalStorage { require(_owner != address(0), "Owner should not be 0x"); require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); // 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"); + uint256 tickerFee = getUint(TICKERREGFEE); + if (tickerFee > 0) + require(IERC20(getAddress(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) - // address previousOwner = _tickerOwner(ticker); - // if (previousOwner != address(0)) { - // _deleteTickerOwnership(previousOwner, ticker); - // } + require(_tickerAvailable(ticker), "Ticker is reserved"); + // Check whether ticker was previously registered (and expired) + address previousOwner = _tickerOwner(ticker); + if (previousOwner != address(0)) { + _deleteTickerOwnership(previousOwner, ticker); + } /*solium-disable-next-line security/no-block-members*/ - bytes4 funcId = InternalRegistry(getAddress("internalContract")).addTicker.selector; - require(getAddress("internalContract").delegatecall.gas(500000)(funcId, _owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, tickerFee)); - //_addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, tickerFee); - } - -// /** -// * @notice Internal - Sets the details of the ticker -// */ -// function _addTicker( -// address _owner, -// string _ticker, -// string _tokenName, -// uint256 _registrationDate, -// uint256 _expiryDate, -// bool _status, -// bool _fromAdmin, -// uint256 _fee -// ) internal { -// _setTickerOwnership(_owner, _ticker); -// _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); -// emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); -// } - -// /** -// * @notice Modifies the ticker details. Only Polymath has the ability to do so. -// * @notice Only allowed to modify the tickers which are not yet deployed. -// * @param _owner is the owner of the token -// * @param _ticker is the token ticker -// * @param _tokenName is the name of the token -// * @param _registrationDate is the date at which ticker is registered -// * @param _expiryDate is the expiry date for the ticker -// * @param _status is the token deployment status -// */ -// function modifyTicker( -// address _owner, -// string _ticker, -// string _tokenName, -// uint256 _registrationDate, -// uint256 _expiryDate, -// bool _status -// ) external onlyOwner { -// require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); -// require(_expiryDate != 0 && _registrationDate != 0, "Dates should not be 0"); -// require(_registrationDate <= _expiryDate, "Registration date should < expiry date"); -// require(_owner != address(0), "Invalid address"); -// string memory ticker = Util.upper(_ticker); -// _modifyTicker(_owner, ticker, _tokenName, _registrationDate, _expiryDate, _status); -// } - -// /** -// * @notice Internal -- Modifies the ticker details. -// */ -// function _modifyTicker( -// address _owner, -// string _ticker, -// string _tokenName, -// uint256 _registrationDate, -// uint256 _expiryDate, -// bool _status -// ) internal { -// address currentOwner = _tickerOwner(_ticker); -// if (currentOwner != address(0)) { -// _deleteTickerOwnership(currentOwner, _ticker); -// } -// if (_tickerStatus(_ticker) && !_status) { -// set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); -// } -// // 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"); -// } -// _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0)); -// } + _addTicker(_owner, ticker, _tokenName, now, now.add(getUint(EXPIRYLIMIT)), false, false, tickerFee); + } + + /** + * @notice Internal - Sets the details of the ticker + */ + function _addTicker( + address _owner, + string _ticker, + string _tokenName, + uint256 _registrationDate, + uint256 _expiryDate, + bool _status, + bool _fromAdmin, + uint256 _fee + ) + internal + { + _setTickerOwnership(_owner, _ticker); + _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); + } + + /** + * @notice Modifies the ticker details. Only Polymath has the ability to do so. + * @notice Only allowed to modify the tickers which are not yet deployed. + * @param _owner is the owner of the token + * @param _ticker is the token ticker + * @param _tokenName is the name of the token + * @param _registrationDate is the date at which ticker is registered + * @param _expiryDate is the expiry date for the ticker + * @param _status is the token deployment status + */ + function modifyTicker( + address _owner, + string _ticker, + string _tokenName, + uint256 _registrationDate, + uint256 _expiryDate, + bool _status + ) + external + onlyOwner + { + require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); + require(_expiryDate != 0 && _registrationDate != 0, "Dates should not be 0"); + require(_registrationDate <= _expiryDate, "Registration date should < expiry date"); + require(_owner != address(0), "Invalid address"); + string memory ticker = Util.upper(_ticker); + _modifyTicker(_owner, ticker, _tokenName, _registrationDate, _expiryDate, _status); + } + + /** + * @notice Internal -- Modifies the ticker details. + */ + function _modifyTicker( + address _owner, + string _ticker, + string _tokenName, + uint256 _registrationDate, + uint256 _expiryDate, + bool _status + ) + internal + { + address currentOwner = _tickerOwner(_ticker); + if (currentOwner != address(0)) { + _deleteTickerOwnership(currentOwner, _ticker); + } + if (_tickerStatus(_ticker) && !_status) { + set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); + } + // 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"); + } + _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)); } -// /** -// * @notice Removes the ticker details, associated ownership & security token mapping -// * @param _ticker is the token ticker -// */ -// function removeTicker(string _ticker) external onlyOwner { -// string memory ticker = Util.upper(_ticker); -// address owner = _tickerOwner(ticker); -// require(owner != address(0), "Ticker doesn't exist"); -// _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); -// } - -// /** -// * @notice Internal - Checks if the entered ticker is registered and has not expired -// * @param _ticker is the token ticker -// * @return bool -// */ -// 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 -// return false; -// } -// return true; -// } + /** + * @notice Removes the ticker details, associated ownership & security token mapping + * @param _ticker is the token ticker + */ + function removeTicker(string _ticker) external onlyOwner { + string memory ticker = Util.upper(_ticker); + address owner = _tickerOwner(ticker); + require(owner != address(0), "Ticker doesn't exist"); + _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); + } + + /** + * @notice Internal - Checks if the entered ticker is registered and has not expired + * @param _ticker is the token ticker + * @return bool + */ + 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 + return false; + } + return true; + } function _tickerStatus(string _ticker) internal view returns(bool) { return getBool(Encoder.getKey("registeredTickers_status", _ticker)); } -// /** -// * @notice Internal - Sets the ticker owner -// * @param _owner is the address of the owner of the ticker -// * @param _ticker is the ticker symbol -// */ -// function _setTickerOwnership(address _owner, string _ticker) internal { -// bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); -// uint256 length = uint256(getArrayBytes32(_ownerKey).length); -// pushArray(_ownerKey, Util.stringToBytes32(_ticker)); -// set(Encoder.getKey("tickerIndex", _ticker), length); -// bytes32 seenKey = Encoder.getKey("seenUsers", _owner); -// if (!getBool(seenKey)) { -// pushArray(Encoder.getKey("activeUsers"), _owner); -// set(seenKey, true); -// } -// } - -// /** -// * @notice Internal - Stores the ticker details -// */ -// function _storeTickerDetails( -// string _ticker, -// address _owner, -// uint256 _registrationDate, -// uint256 _expiryDate, -// string _tokenName, -// bool _status -// ) internal { -// bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); -// if (getAddress(key) != _owner) -// set(key, _owner); -// key = Encoder.getKey("registeredTickers_registrationDate", _ticker); -// if (getUint(key) != _registrationDate) -// set(key, _registrationDate); -// key = Encoder.getKey("registeredTickers_expiryDate", _ticker); -// if (getUint(key) != _expiryDate) -// set(key, _expiryDate); -// key = Encoder.getKey("registeredTickers_tokenName", _ticker); -// if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) -// set(key, _tokenName); -// key = Encoder.getKey("registeredTickers_status", _ticker); -// if (getBool(key) != _status) -// set(key, _status); -// } - -// /** -// * @notice Transfers the ownership of the ticker -// * @param _newOwner is the address of the new owner of the ticker -// * @param _ticker is the ticker symbol -// */ -// function transferTickerOwnership(address _newOwner, string _ticker) external whenNotPausedOrOwner { -// 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"); -// if (_tickerStatus(ticker)) -// require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); -// _deleteTickerOwnership(msg.sender, ticker); -// _setTickerOwnership(_newOwner, ticker); -// set(ownerKey, _newOwner); -// emit ChangeTickerOwnership(ticker, msg.sender, _newOwner); -// } - -// /** -// * @notice Internal - Removes the owner of a ticker -// */ -// function _deleteTickerOwnership(address _owner, string _ticker) internal { -// uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); -// bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); -// bytes32[] memory tickers = getArrayBytes32(ownerKey); -// assert(index < tickers.length); -// assert(_tickerOwner(_ticker) == _owner); -// deleteArrayBytes32(ownerKey, index); -// if (getArrayBytes32(ownerKey).length > index) { -// bytes32 switchedTicker = getArrayBytes32(ownerKey)[index]; -// set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); -// } -// } - -// /** -// * @notice Changes the expiry time for the token ticker. Only available to Polymath. -// * @param _newExpiry is the new expiry for newly generated tickers -// */ -// function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { -// require(_newExpiry >= 1 days, "Expiry should >= 1 day"); -// emit ChangeExpiryLimit(getUint(EXPIRYLIMIT), _newExpiry); -// set(EXPIRYLIMIT, _newExpiry); -// } - -// /** -// * @notice Returns the list of tickers owned by the selected address -// * @param _owner is the address which owns the list of tickers -// */ -// function getTickersByOwner(address _owner) external view returns(bytes32[]) { -// uint counter = 0; -// // accessing the data structure userTotickers[_owner].length -// bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); -// 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)) { -// counter ++; -// } -// } -// bytes32[] memory tempList = new bytes32[](counter); -// counter = 0; -// 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)) { -// tempList[counter] = tickers[i]; -// counter ++; -// } -// } -// return tempList; -// } - -// /** -// * @notice Returns the list of tokens owned by the selected address -// * @param _owner is the address which owns the list of tickers -// * @dev Intention is that this is called off-chain so block gas limit is not relevant -// */ -// function getTokensByOwner(address _owner) external view returns(address[]) { -// // Loop over all active users, then all associated tickers of those users -// // This ensures we find tokens, even if their owner has been modified -// address[] memory activeUsers = getArrayAddress(Encoder.getKey("activeUsers")); -// bytes32[] memory tickers; -// address token; -// uint256 count = 0; -// uint256 i = 0; -// uint256 j = 0; -// 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]))); -// if (token != address(0)) { -// if (IOwnable(token).owner() == _owner) { -// count = count + 1; -// } -// } -// } -// } -// uint256 index = 0; -// address[] memory result = new address[](count); -// 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]))); -// if (token != address(0)) { -// if (IOwnable(token).owner() == _owner) { -// result[index] = token; -// index = index + 1; -// } -// } -// } -// } -// return result; -// } - - /** - * @notice Returns the owner and timestamp for a given ticker + /** + * @notice Internal - Sets the ticker owner + * @param _owner is the address of the owner of the ticker * @param _ticker is the ticker symbol - * @return address - * @return uint256 - * @return uint256 - * @return string - * @return bool */ - function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool) { + function _setTickerOwnership(address _owner, string _ticker) internal { + bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); + uint256 length = uint256(getArrayBytes32(_ownerKey).length); + pushArray(_ownerKey, Util.stringToBytes32(_ticker)); + set(Encoder.getKey("tickerIndex", _ticker), length); + bytes32 seenKey = Encoder.getKey("seenUsers", _owner); + if (!getBool(seenKey)) { + pushArray(Encoder.getKey("activeUsers"), _owner); + set(seenKey, true); + } + } + + /** + * @notice Internal - Stores the ticker details + */ + function _storeTickerDetails( + string _ticker, + address _owner, + uint256 _registrationDate, + uint256 _expiryDate, + string _tokenName, + bool _status + ) + internal + { + bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); + if (getAddress(key) != _owner) + set(key, _owner); + key = Encoder.getKey("registeredTickers_registrationDate", _ticker); + if (getUint(key) != _registrationDate) + set(key, _registrationDate); + key = Encoder.getKey("registeredTickers_expiryDate", _ticker); + if (getUint(key) != _expiryDate) + set(key, _expiryDate); + key = Encoder.getKey("registeredTickers_tokenName", _ticker); + if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) + set(key, _tokenName); + key = Encoder.getKey("registeredTickers_status", _ticker); + if (getBool(key) != _status) + set(key, _status); + } + + /** + * @notice Transfers the ownership of the ticker + * @param _newOwner is the address of the new owner of the ticker + * @param _ticker is the ticker symbol + */ + function transferTickerOwnership(address _newOwner, string _ticker) external whenNotPausedOrOwner { 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 - ( - _tickerOwner(ticker), - getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), - expiryDate, - getString(Encoder.getKey("registeredTickers_tokenName", ticker)), - tickerStatus - ); - } else - return (address(0), uint256(0), uint256(0), "", false); - } - -// ///////////////////////////// -// // Security Token Management -// ///////////////////////////// - -// /** -// * @notice Deploys an instance of a new Security Token and records it to the registry -// * @param _name is the name of the token -// * @param _ticker is the ticker symbol of the security token -// * @param _tokenDetails is the off-chain details of the token -// * @param _divisible is whether or not the token is divisible -// */ -// function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external whenNotPausedOrOwner { -// 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"); -// 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(); -// if (launchFee > 0) -// require(IERC20(getAddress(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); - -// address newSecurityTokenAddress = ISTFactory(getSTFactoryAddress()).deployToken( -// _name, -// ticker, -// 18, -// _tokenDetails, -// msg.sender, -// _divisible, -// 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); -// } - -// /** -// * @notice Adds a new custom Security Token and saves it to the registry. (Token should follow the ISecurityToken interface) -// * @param _name is the name of the token -// * @param _ticker is the ticker symbol of the security token -// * @param _owner is the owner of the token -// * @param _securityToken is the address of the securityToken -// * @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 -// { -// 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"); -// 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)); -// if (registrationTime == 0) { -// /*solium-disable-next-line security/no-block-members*/ -// registrationTime = now; -// expiryTime = registrationTime.add(getExpiryLimit()); -// } -// set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); -// _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); -// _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); -// emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getSecurityTokenLaunchFee()); -// } - -// /** -// * @notice Internal - Stores the security token details -// */ -// function _storeSecurityTokenData(address _securityToken, string _ticker, string _tokenDetails, uint256 _deployedAt) internal { -// set(Encoder.getKey("securityTokens_ticker", _securityToken), _ticker); -// set(Encoder.getKey("securityTokens_tokenDetails", _securityToken), _tokenDetails); -// set(Encoder.getKey("securityTokens_deployedAt", _securityToken), _deployedAt); -// } - -// /** -// * @notice Checks that Security Token is registered -// * @param _securityToken is the address of the security token -// * @return bool -// */ -// function isSecurityToken(address _securityToken) external view returns (bool) { -// return (keccak256(bytes(getString(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); -// } - -// /** -// * @notice Returns the security token address by ticker symbol -// * @param _ticker is the ticker of the security token -// * @return address -// */ -// function getSecurityTokenAddress(string _ticker) external view returns (address) { -// string memory ticker = Util.upper(_ticker); -// return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); -// } - -// /** -// * @notice Returns the security token data by address -// * @param _securityToken is the address of the security token. -// * @return string is the ticker of the security Token. -// * @return address is the issuer of the security Token. -// * @return string is the details of the security token. -// * @return uint256 is the timestamp at which security Token was deployed. -// */ -// function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256) { -// return ( -// getString(Encoder.getKey("securityTokens_ticker", _securityToken)), -// IOwnable(_securityToken).owner(), -// getString(Encoder.getKey("securityTokens_tokenDetails", _securityToken)), -// getUint(Encoder.getKey("securityTokens_deployedAt", _securityToken)) -// ); -// } - -// ///////////////////////////// -// // Ownership, lifecycle & Utility -// ///////////////////////////// - -// /** -// * @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 onlyOwner { -// require(_newOwner != address(0), "Invalid address"); -// emit OwnershipTransferred(getAddress(OWNER), _newOwner); -// set(OWNER, _newOwner); -// } - -// /** -// * @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 -// */ -// function unpause() external whenPaused onlyOwner { -// set(PAUSED, false); -// /*solium-disable-next-line security/no-block-members*/ -// emit Unpause(now); -// } - -// /** -// * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. -// * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) -// */ -// function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { -// uint256 fee = getUint(TICKERREGFEE); -// require(fee != _tickerRegFee, "Fee not changed"); -// emit ChangeTickerRegistrationFee(fee, _tickerRegFee); -// set(TICKERREGFEE, _tickerRegFee); -// } - -// /** -// * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. -// * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) -// */ -// function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { -// uint256 fee = getUint(STLAUNCHFEE); -// require(fee != _stLaunchFee, "Fee not changed"); -// emit ChangeSecurityLaunchFee(fee, _stLaunchFee); -// set(STLAUNCHFEE, _stLaunchFee); -// } - -// /** -// * @notice Reclaims all ERC20Basic compatible tokens -// * @param _tokenContract is 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(owner(), balance), "Transfer failed"); -// } - -// /** -// * @notice Changes the protocol version and the SecurityToken contract -// * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions -// * @notice Changing versions does not affect existing tokens. -// * @param _STFactoryAddress is the address of the proxy. -// * @param _major Major version of the proxy. -// * @param _minor Minor version of the proxy. -// * @param _patch Patch version of the proxy -// */ -// function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { -// require(_STFactoryAddress != address(0), "0x address is not allowed"); -// _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); -// } + require(_newOwner != address(0), "Invalid address"); + bytes32 ownerKey = Encoder.getKey("registeredTickers_owner", ticker); + require(getAddress(ownerKey) == msg.sender, "Not authorised"); + if (_tickerStatus(ticker)) + require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); + _deleteTickerOwnership(msg.sender, ticker); + _setTickerOwnership(_newOwner, ticker); + set(ownerKey, _newOwner); + emit ChangeTickerOwnership(ticker, msg.sender, _newOwner); + } /** - * @notice Internal - Changes the protocol version and the SecurityToken contract - */ - function _setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) internal { - uint8[] memory _version = new uint8[](3); - _version[0] = _major; - _version[1] = _minor; - _version[2] = _patch; - 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); + * @notice Internal - Removes the owner of a ticker + */ + function _deleteTickerOwnership(address _owner, string _ticker) internal { + uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); + bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); + bytes32[] memory tickers = getArrayBytes32(ownerKey); + assert(index < tickers.length); + assert(_tickerOwner(_ticker) == _owner); + deleteArrayBytes32(ownerKey, index); + if (getArrayBytes32(ownerKey).length > index) { + bytes32 switchedTicker = getArrayBytes32(ownerKey)[index]; + set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); + } + } + + /** + * @notice Changes the expiry time for the token ticker. Only available to Polymath. + * @param _newExpiry is the new expiry for newly generated tickers + */ + function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { + require(_newExpiry >= 1 days, "Expiry should >= 1 day"); + emit ChangeExpiryLimit(getUint(EXPIRYLIMIT), _newExpiry); + set(EXPIRYLIMIT, _newExpiry); } -// /** -// * @notice Returns the current STFactory Address -// */ -// function getSTFactoryAddress() public view returns(address) { -// return getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion")))); -// } + ///////////////////////////// + // Security Token Management + ///////////////////////////// /** - * @notice Gets Protocol version + * @notice Deploys an instance of a new Security Token and records it to the registry + * @param _name is the name of the token + * @param _ticker is the ticker symbol of the security token + * @param _tokenDetails is the off-chain details of the token + * @param _divisible is whether or not the token is divisible */ - function getProtocolVersion() public view returns(uint8[]) { - return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); + function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external whenNotPausedOrOwner { + 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"); + 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 = getUint(STLAUNCHFEE); + if (launchFee > 0) + require(IERC20(getAddress(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); + + address newSecurityTokenAddress = ISTFactory(getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))))).deployToken( + _name, + ticker, + 18, + _tokenDetails, + msg.sender, + _divisible, + 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); } /** - * @notice Gets the security token launch fee - * @return Fee amount + * @notice Adds a new custom Security Token and saves it to the registry. (Token should follow the ISecurityToken interface) + * @param _name is the name of the token + * @param _ticker is the ticker symbol of the security token + * @param _owner is the owner of the token + * @param _securityToken is the address of the securityToken + * @param _tokenDetails is the off-chain details of the token + * @param _deployedAt is the timestamp at which the security token is deployed */ - function getSecurityTokenLaunchFee() public view returns(uint256) { - return getUint(STLAUNCHFEE); + 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"); + 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)); + if (registrationTime == 0) { + /*solium-disable-next-line security/no-block-members*/ + registrationTime = now; + expiryTime = registrationTime.add(getUint(EXPIRYLIMIT)); + } + set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); + _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); + _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); + emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getUint(STLAUNCHFEE)); } /** - * @notice Gets the ticker registration fee - * @return Fee amount + * @notice Internal - Stores the security token details */ - function getTickerRegistrationFee() public view returns(uint256) { - return getUint(TICKERREGFEE); + function _storeSecurityTokenData(address _securityToken, string _ticker, string _tokenDetails, uint256 _deployedAt) internal { + set(Encoder.getKey("securityTokens_ticker", _securityToken), _ticker); + set(Encoder.getKey("securityTokens_tokenDetails", _securityToken), _tokenDetails); + set(Encoder.getKey("securityTokens_deployedAt", _securityToken), _deployedAt); + } + + /** + * @notice Checks that Security Token is registered + * @param _securityToken is the address of the security token + * @return bool + */ + function isSecurityToken(address _securityToken) external view returns (bool) { + return (keccak256(bytes(getString(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); + } + + ///////////////////////////// + // Ownership, lifecycle & Utility + ///////////////////////////// + + /** + * @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 onlyOwner { + require(_newOwner != address(0), "Invalid address"); + emit OwnershipTransferred(getAddress(OWNER), _newOwner); + set(OWNER, _newOwner); + } + + /** + * @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 + */ + function unpause() external whenPaused onlyOwner { + set(PAUSED, false); + /*solium-disable-next-line security/no-block-members*/ + emit Unpause(now); + } + + /** + * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. + * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) + */ + function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { + uint256 fee = getUint(TICKERREGFEE); + require(fee != _tickerRegFee, "Fee not changed"); + emit ChangeTickerRegistrationFee(fee, _tickerRegFee); + set(TICKERREGFEE, _tickerRegFee); + } + + /** + * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. + * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) + */ + function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { + uint256 fee = getUint(STLAUNCHFEE); + require(fee != _stLaunchFee, "Fee not changed"); + emit ChangeSecurityLaunchFee(fee, _stLaunchFee); + set(STLAUNCHFEE, _stLaunchFee); + } + + /** + * @notice Reclaims all ERC20Basic compatible tokens + * @param _tokenContract is 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(owner(), balance), "Transfer failed"); + } + + /** + * @notice Changes the protocol version and the SecurityToken contract + * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions + * @notice Changing versions does not affect existing tokens. + * @param _STFactoryAddress is the address of the proxy. + * @param _major Major version of the proxy. + * @param _minor Minor version of the proxy. + * @param _patch Patch version of the proxy + */ + function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { + require(_STFactoryAddress != address(0), "0x address is not allowed"); + _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); + } + + /** + * @notice Internal - Changes the protocol version and the SecurityToken contract + */ + function _setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) internal { + uint8[] memory _version = new uint8[](3); + _version[0] = _major; + _version[1] = _minor; + _version[2] = _patch; + uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); + require( + VersionUtils.isValidVersion(VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))), _version), + "In-valid version" + ); + set(Encoder.getKey("latestVersion"), uint256(_packedVersion)); + set(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))), _STFactoryAddress); } /** - * @notice Gets the expiry limit - * @return Expiry limit + * @notice Changes the PolyToken address. Only Polymath. + * @param _newAddress is the address of the polytoken. */ - function getExpiryLimit() public view returns(uint256) { - return getUint(EXPIRYLIMIT); + function updatePolyTokenAddress(address _newAddress) external onlyOwner { + require(_newAddress != address(0), "Invalid address"); + set(POLYTOKEN, _newAddress); } /** diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 5b49044fa..ca24170c5 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -27,7 +27,7 @@ const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') const MockOracle = artifacts.require('./MockOracle.sol') const TokenLib = artifacts.require('./TokenLib.sol'); const SecurityToken = artifacts.require('./tokens/SecurityToken.sol') -const InternalRegistry = artifacts.require('./InternalRegistry.sol'); +const STRGetter = artifacts.require('./STRGetter.sol'); let BigNumber = require('bignumber.js'); const cappedSTOSetupCost = new BigNumber(20000).times(new BigNumber(10).pow(18)); // 20K POLY fee @@ -112,6 +112,9 @@ module.exports = function (deployer, network, accounts) { },{ type: 'address', name: '_owner' + },{ + type: 'address', + name: '_getterContract' }] }; @@ -231,10 +234,10 @@ module.exports = function (deployer, network, accounts) { }).then(()=> { return deployer.deploy(SecurityTokenRegistryProxy, {from: PolymathAccount}); }).then(() => { - let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolymathAccount]); - return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); + return deployer.deploy(STRGetter, {from: PolymathAccount}); }).then(() => { - return deployer.deploy(InternalRegistry, {from: PolymathAccount}); + let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolymathAccount, STRGetter.address]); + return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); }).then(() => { // Assign the address into the SecurityTokenRegistry key return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); @@ -342,7 +345,7 @@ module.exports = function (deployer, network, accounts) { SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} ModuleRegistry (Proxy): ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} - InternalRegsitry: ${InternalRegistry.address} + STRGetter: ${STRGetter.address} ETHOracle: ${ETHOracle} POLYOracle: ${POLYOracle} diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index a319c0e23..ab8f32688 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -58,6 +58,7 @@ contract("CappedSTO", accounts => { let I_PolymathRegistry; let I_STRProxied; let I_MRProxied; + let I_STRGetter; let pauseTime; // SecurityToken Details for funds raise Type ETH @@ -125,7 +126,8 @@ contract("CappedSTO", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 4472ba5ca..2e7e6987f 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -44,6 +44,7 @@ contract("Checkpoints", accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -86,7 +87,8 @@ contract("Checkpoints", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // Printing all the contract addresses diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 62cb7223b..2e42fb093 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -54,6 +54,7 @@ contract("CountTransferManager", accounts => { let I_SecurityToken2; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -101,7 +102,8 @@ contract("CountTransferManager", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the CountTransferManager diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index f41b5575d..7c9836d42 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -54,6 +54,7 @@ contract("ERC20DividendCheckpoint", accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -104,7 +105,8 @@ contract("ERC20DividendCheckpoint", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; [P_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 89202579b..25bacb792 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -54,6 +54,7 @@ contract("EtherDividendCheckpoint", accounts => { let I_PolyToken; let I_MRProxied; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -100,7 +101,8 @@ contract("EtherDividendCheckpoint", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; [P_EtherDividendCheckpointFactory] = await deployEtherDividendAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index e255ff0ce..c1081ddbc 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -54,6 +54,7 @@ contract('GeneralPermissionManager', accounts => { let I_STRProxied; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -99,7 +100,8 @@ contract('GeneralPermissionManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 6203d3574..457898b58 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -58,6 +58,7 @@ contract("GeneralTransferManager", accounts => { let I_PolyToken; let I_PolymathRegistry; let P_GeneralTransferManagerFactory; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -112,7 +113,8 @@ contract("GeneralTransferManager", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 048ea5060..9a8ada346 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -37,6 +37,7 @@ const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const DummySTO = artifacts.require("./DummySTO.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); +const STRGetter = artifacts.require("./STRGetter.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); const Web3 = require("web3"); @@ -83,11 +84,12 @@ let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; +let I_STRGetter; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); -const STRProxyParameters = ["address", "address", "uint256", "uint256", "address"]; +const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; const MRProxyParameters = ["address", "address"]; /// Function use to launch the polymath ecossystem. @@ -192,17 +194,20 @@ async function deploySTR(account_polymath) { // Step 9 (a): Deploy the proxy I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ from: account_polymath }); + I_STRGetter = await STRGetter.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }); I_STRProxied = SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - return new Array(I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied); + return new Array(I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, I_STRGetter); } async function setInPolymathRegistry(account_polymath) { diff --git a/test/i_Issuance.js b/test/i_Issuance.js index b85dea7e1..179b571f1 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -51,6 +51,7 @@ contract("Issuance", accounts => { let I_CappedSTO; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -104,7 +105,8 @@ contract("Issuance", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 8df86241e..41fabbd46 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -55,6 +55,7 @@ contract("ManualApprovalTransferManager", accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -100,7 +101,8 @@ contract("ManualApprovalTransferManager", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory diff --git a/test/k_module_registry.js b/test/k_module_registry.js index c5e5535a6..ec58b28e9 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -66,6 +66,7 @@ contract("ModuleRegistry", accounts => { let I_DummySTOFactory; let I_PolymathRegistry; let I_SecurityToken2; + let I_STRGetter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -121,7 +122,8 @@ contract("ModuleRegistry", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: account_polymath}); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index e889c79d0..c3d08ba58 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -50,7 +50,8 @@ contract("PercentageTransferManager", accounts => { let I_STFactory; let I_SecurityToken; let I_PolyToken; - var I_PolymathRegistry; + let I_STRGetter; + let I_PolymathRegistry; // SecurityToken Details const name = "Team"; @@ -109,7 +110,8 @@ contract("PercentageTransferManager", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index eadf597c6..696ec92a1 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -49,6 +49,7 @@ contract("PreSaleSTO", accounts => { let I_PreSaleSTO; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details for funds raise Type ETH const name = "Team"; @@ -96,7 +97,8 @@ contract("PreSaleSTO", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 4: Deploy the PreSaleSTOFactory diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 0383e2fc3..e9bca4d07 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -11,7 +11,7 @@ const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryPro const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); const STFactory = artifacts.require("./STFactory.sol"); -const InternalRegistry = artifacts.require('./InternalRegistry.sol'); +const STRGetter = artifacts.require('./STRGetter.sol'); const Web3 = require("web3"); @@ -60,7 +60,8 @@ contract("SecurityTokenRegistry", accounts => { let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; - let I_InternalRegistry; + let I_STRGetter; + let I_Getter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -84,7 +85,7 @@ contract("SecurityTokenRegistry", accounts => { const initRegFee = web3.utils.toWei("250"); const newRegFee = web3.utils.toWei("300"); - const STRProxyParameters = ["address", "address", "uint256", "uint256", "address"]; + const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; const STOParameters = ["uint256", "uint256", "uint256", "string"]; // Capped STO details @@ -116,16 +117,18 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 8: Deploy the CappedSTOFactory [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, 0); // Step 9: Deploy the SecurityTokenRegistry - + console.log(I_SecurityTokenRegistry.address); I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ from: account_polymath }); - + console.log(I_SecurityTokenRegistry.address); + assert.notEqual( I_SecurityTokenRegistry.address.valueOf(), address_zero, @@ -134,6 +137,8 @@ contract("SecurityTokenRegistry", accounts => { // Step 9 (a): Deploy the proxy I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ from: account_polymath }); + // Step 10 : Deploy the getter contract + I_STRGetter = await STRGetter.new({ from: account_polymath }); //Step 11: update the registries addresses from the PolymathRegistry contract await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, { from: account_polymath }); await I_MRProxied.updateFromRegistry({ from: account_polymath }); @@ -162,9 +167,10 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ]); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }), @@ -178,9 +184,10 @@ contract("SecurityTokenRegistry", accounts => { address_zero, initRegFee, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ]); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }), @@ -194,9 +201,10 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, 0, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ]); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }), @@ -210,25 +218,27 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, 0, - account_polymath + account_polymath, + I_STRGetter.address ]); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }), "tx-> revert because tickerRegFee is 0" ); }); - + it("Should successfully update the implementation address -- fail because owner address is 0x", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, - address_zero + address_zero, + I_STRGetter.address ]); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }), @@ -242,9 +252,10 @@ contract("SecurityTokenRegistry", accounts => { address_zero, 0, 0, + address_zero, address_zero ]); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }), @@ -258,11 +269,13 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }); + I_Getter = STRGetter.at(I_SecurityTokenRegistryProxy.address); I_STRProxied = SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); }); }); @@ -287,25 +300,29 @@ contract("SecurityTokenRegistry", accounts => { 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 getterContract = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("STRGetter")); + assert.equal(getterContract, I_STRGetter.address, "Should be the address of the getter contract"); + 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 () => { - catchRevert( + await catchRevert( I_STRProxied.initialize( I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ), "tx revert -> Can't call the intialize function again" ); }); it("Should fail to register ticker if tickerRegFee not approved", async () => { - catchRevert( + await catchRevert( I_STRProxied.registerTicker(account_temp, symbol, name, { from: account_temp }), "tx revert -> POLY allowance not provided for registration fee" ); @@ -315,18 +332,18 @@ contract("SecurityTokenRegistry", accounts => { await I_PolyToken.getTokens(initRegFee, account_temp); await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp }); - catchRevert( + await catchRevert( I_STRProxied.registerTicker(address_zero, symbol, name, { from: account_temp }), "tx revert -> owner should not be 0x" ); }); it("Should fail to register ticker due to the symbol length is 0", async () => { - catchRevert(I_STRProxied.registerTicker(account_temp, "", name, { from: account_temp }), "tx revert -> Symbol Length is 0"); + await catchRevert(I_STRProxied.registerTicker(account_temp, "", name, { from: account_temp }), "tx revert -> Symbol Length is 0"); }); it("Should fail to register ticker due to the symbol length is greater than 10", async () => { - catchRevert( + await catchRevert( I_STRProxied.registerTicker(account_temp, "POLYMATHNET", name, { from: account_temp }), "tx revert -> Symbol Length is greater than 10" ); @@ -334,74 +351,75 @@ contract("SecurityTokenRegistry", accounts => { 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 }); - console.log(tx); - // 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}`); - console.log(await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("internalContract"))); - console.log(I_InternalRegistry.address); - console.log(await I_STRProxied.getTickerDetails.call(symbol)); - console.log(await I_InternalRegistry.getUintValues.call(web3.utils.soliditySha3("registeredTickers_expiryDate",symbol))); - console.log(await I_SecurityTokenRegistry.getTickerDetails.call(symbol)); - }); - - // it("Should register the ticker when the tickerRegFee is 0", async() => { - // let snap_Id = await takeSnapshot(); - // await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); - // let tx = await I_STRProxied.registerTicker(account_temp, "ZERO", 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, "ZERO", `Symbol should be ZERO`); - // await revertToSnapshot(snap_Id); - // }) - - // it("Should fail to register same symbol again", async () => { - // // Give POLY to token issuer - // await I_PolyToken.getTokens(initRegFee, token_owner); - // await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - // // Call registration function - // catchRevert( - // I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }), - // "tx revert -> Symbol is already alloted to someone else" - // ); - // }); - - // 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 () => { - // await I_STRProxied.pause({ from: account_polymath }); - // await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - - // catchRevert( - // I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }), - // "tx revert -> Registration is paused" - // ); - // }); - - // it("Should fail to pause if already paused", async () => { - // catchRevert(I_STRProxied.pause({ from: account_polymath }), "tx revert -> Registration is already paused"); - // }); - - // 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 () => { - // catchRevert(I_STRProxied.unpause({ from: account_polymath }), "tx revert -> Registration is already unpaused"); - // }); + 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}`); + let data = await I_Getter.getTickerDetails.call(symbol); + assert.equal(data[0], account_temp); + assert.equal(data[3], name); + // trying to access the function data directly from the STRGetter then it should give all values zero + data = await I_STRGetter.getTickerDetails.call(symbol); + assert.equal(data[0], address_zero); + assert.equal(data[3], ""); + }); + + it("Should register the ticker when the tickerRegFee is 0", async() => { + let snap_Id = await takeSnapshot(); + await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); + let tx = await I_STRProxied.registerTicker(account_temp, "ZERO", 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, "ZERO", `Symbol should be ZERO`); + await revertToSnapshot(snap_Id); + }) + + it("Should fail to register same symbol again", async () => { + // Give POLY to token issuer + await I_PolyToken.getTokens(initRegFee, token_owner); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + // Call registration function + await catchRevert( + I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }), + "tx revert -> Symbol is already alloted to someone else" + ); + }); + + 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 () => { + await I_STRProxied.pause({ from: account_polymath }); + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + + await catchRevert( + I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }), + "tx revert -> Registration is paused" + ); + }); + + it("Should fail to pause if already paused", async () => { + await catchRevert(I_STRProxied.pause({ from: account_polymath }), "tx revert -> Registration is already paused"); + }); + + 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 () => { + await catchRevert(I_STRProxied.unpause({ from: account_polymath }), "tx revert -> Registration is already unpaused"); + }); }); - describe.skip("Test cases for the expiry limit", async () => { + describe("Test cases for the expiry limit", async () => { it("Should fail to set the expiry limit because msg.sender is not owner", async () => { - catchRevert(I_STRProxied.changeExpiryLimit(duration.days(10), { from: account_temp }), "tx revert -> msg.sender is not owner"); + await catchRevert(I_STRProxied.changeExpiryLimit(duration.days(10), { from: account_temp }), "tx revert -> msg.sender is not owner"); }); it("Should successfully set the expiry limit", async () => { @@ -414,36 +432,36 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail to set the expiry limit because new expiry limit is lesser than one day", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeExpiryLimit(duration.seconds(5000), { from: account_polymath }), "tx revert -> New expiry limit is lesser than one day" ); }); }); - describe.skip("Test cases for the getTickerDetails", async () => { + describe("Test cases for the getTickerDetails", async () => { it("Should get the details of the symbol", async () => { - let tx = await I_STRProxied.getTickerDetails.call(symbol); + let tx = await I_Getter.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"); + let tx = await I_Getter.getTickerDetails.call("TORO"); assert.equal(tx[0], address_zero, "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.skip("Generate SecurityToken", async () => { + 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 }); + let data = await I_Getter.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 }); + data = await I_STRGetter.getTickerDetails(symbol, { from: token_owner }); console.log("This is the data from the original securityTokenRegistry contract"); assert.equal(data[0], address_zero, "Token owner should be 0x"); }); @@ -451,7 +469,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail to generate new security token if fee not provided", async () => { await I_PolyToken.approve(I_STRProxied.address, 0, { from: token_owner }); - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }), "tx revert -> POLY allowance not provided for registration fee" ); @@ -461,7 +479,7 @@ contract("SecurityTokenRegistry", accounts => { await I_STRProxied.pause({ from: account_polymath }); await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }), "tx revert -> Registration is paused" ); @@ -470,21 +488,21 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail to generate the securityToken -- Because ticker length is 0", async () => { await I_STRProxied.unpause({ from: account_polymath }); - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken(name, "", tokenDetails, false, { from: token_owner }), "tx revert -> Zero ticker length is not allowed" ); }); it("Should fail to generate the securityToken -- Because name length is 0", async () => { - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: token_owner }), "tx revert -> 0 name length is not allowed" ); }); it("Should fail to generate the securityToken -- Because msg.sender is not the rightful owner of the ticker", async () => { - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_temp }), "tx revert -> Because msg.sender is not the rightful owner of the ticker" ); @@ -507,7 +525,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail to generate the SecurityToken when token is already deployed with the same symbol", async () => { - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }), "tx revert -> Because ticker is already in use" ); @@ -518,7 +536,7 @@ contract("SecurityTokenRegistry", accounts => { await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner }); let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); await increaseTime(duration.days(65)); - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken(name, "CCC", tokenDetails, false, { from: token_owner }), "tx revert -> Because ticker is expired" ); @@ -535,7 +553,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe.skip("Generate SecurityToken v2", async () => { + describe("Generate SecurityToken v2", async () => { it("Should deploy the st version 2", async () => { // Step 7: Deploy the STFactory contract @@ -547,7 +565,7 @@ contract("SecurityTokenRegistry", accounts => { "STFactory002 contract was not deployed" ); await I_STRProxied.setProtocolVersion(I_STFactory002.address, 2, 2, 0, { from: account_polymath }); - let _protocol = await I_STRProxied.getProtocolVersion.call(); + let _protocol = await I_Getter.getProtocolVersion.call(); assert.equal(_protocol[0], 2); assert.equal(_protocol[1], 2); assert.equal(_protocol[2], 0); @@ -569,7 +587,7 @@ contract("SecurityTokenRegistry", accounts => { assert.equal(tx.logs[2].args._ticker, symbol2, "SecurityToken doesn't get deployed"); I_SecurityToken002 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); - let tokens = await I_STRProxied.getTokensByOwner.call(token_owner); + let tokens = await I_Getter.getTokensByOwner.call(token_owner); assert.equal(tokens[0], I_SecurityToken.address); assert.equal(tokens[1], I_SecurityToken002.address); @@ -580,7 +598,7 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe.skip("Deploy the new SecurityTokenRegistry", async () => { + 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( @@ -606,7 +624,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should check the old data persist or not", async () => { - let data = await I_STRProxied.getTickerDetails.call(symbol); + let data = await I_Getter.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"); @@ -618,9 +636,9 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe.skip("Generate custom tokens", async () => { + describe("Generate custom tokens", async () => { it("Should fail if msg.sender is not polymath", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), { from: account_delegate }), @@ -629,7 +647,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail to genrate the custom security token -- ticker length is greater than 10 chars", async() => { - catchRevert( + await catchRevert( I_STRProxied.modifySecurityToken("LOGAN", "LOGLOGLOGLOG", account_temp, dummy_token, "I am custom ST", latestTime(), { from: account_polymath }), @@ -638,7 +656,7 @@ contract("SecurityTokenRegistry", accounts => { }) it("Should fail to generate the custom security token -- name should not be 0 length ", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), { from: account_polymath }), @@ -647,7 +665,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail if ST address is 0 address", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, 0, "I am custom ST", latestTime(), { from: account_polymath }), @@ -656,7 +674,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail if symbol length is 0", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifySecurityToken("", "", account_temp, dummy_token, "I am custom ST", latestTime(), { from: account_polymath }), @@ -665,7 +683,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail to generate the custom ST -- deployedAt param is 0", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", 0, { from: account_polymath }), "tx revert -> because deployedAt param is 0" ); @@ -675,16 +693,16 @@ contract("SecurityTokenRegistry", accounts => { // 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); + let tickersListArray = await I_Getter.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); + tickersListArray = await I_Getter.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); + tickersListArray = await I_Getter.getTickersByOwner.call(account_temp); console.log(tickersListArray); assert.equal(tx.logs[1].args._ticker, "LOG", "Symbol should match with the registered symbol"); assert.equal( @@ -692,7 +710,7 @@ contract("SecurityTokenRegistry", accounts => { dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken` ); - let symbolDetails = await I_STRProxied.getTickerDetails("LOG"); + let symbolDetails = await I_Getter.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`); }); @@ -714,7 +732,7 @@ contract("SecurityTokenRegistry", accounts => { ); 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"); + let symbolDetails = await I_Getter.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`); }); @@ -728,7 +746,7 @@ contract("SecurityTokenRegistry", accounts => { describe("Test case for modifyTicker", async () => { it("Should add the custom ticker --failed because of bad owner", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), latestTime() + duration.days(10), false, { from: account_temp }), @@ -737,7 +755,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the custom ticker --fail ticker length should not be 0", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifyTicker(token_owner, "", "Ether", latestTime(), latestTime() + duration.days(10), false, { from: account_polymath }), @@ -746,7 +764,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the custom ticker --failed because time should not be 0", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", 0, latestTime() + duration.days(10), false, { from: account_polymath }), @@ -755,7 +773,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the custom ticker --failed because registeration date is greater than the expiryDate", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), latestTime() - duration.minutes(10), false, { from: account_polymath }), @@ -764,7 +782,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the custom ticker --failed because owner should not be 0x", async () => { - catchRevert( + await catchRevert( I_STRProxied.modifyTicker( "0x000000000000000000000000000000000000000000", "ETH", @@ -808,7 +826,7 @@ contract("SecurityTokenRegistry", accounts => { 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 () => { - catchRevert( + await catchRevert( I_STRProxied.transferTickerOwnership(account_issuer, "ETH", { from: account_temp }), "tx revert -> failed because token is not deployed having the same ticker" ); @@ -816,14 +834,14 @@ contract("SecurityTokenRegistry", accounts => { it("Should able to transfer the ticker ownership -- failed because new owner is 0x", async () => { await I_SecurityToken002.transferOwnership(account_temp, { from: token_owner }); - catchRevert( + await catchRevert( I_STRProxied.transferTickerOwnership("0x00000000000000000000000000000000000000000", symbol2, { from: token_owner }), "tx revert -> failed because new owner is 0x" ); }); it("Should able to transfer the ticker ownership -- failed because ticker is of zero length", async () => { - catchRevert( + await catchRevert( I_STRProxied.transferTickerOwnership(account_temp, "", { from: token_owner }), "tx revert -> failed because ticker is of zero length" ); @@ -832,7 +850,7 @@ contract("SecurityTokenRegistry", accounts => { 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); + let symbolDetails = await I_Getter.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}`); }); @@ -840,14 +858,14 @@ contract("SecurityTokenRegistry", accounts => { describe("Test case for the changeSecurityLaunchFee()", async () => { it("Should able to change the STLaunchFee-- failed because of bad owner", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), { from: account_temp }), "tx revert -> failed because of bad owner" ); }); it("Should able to change the STLaunchFee-- failed because of putting the same fee", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeSecurityLaunchFee(initRegFee, { from: account_polymath }), "tx revert -> failed because of putting the same fee" ); @@ -863,14 +881,14 @@ contract("SecurityTokenRegistry", accounts => { describe("Test cases for the changeExpiryLimit()", async () => { it("Should able to change the ExpiryLimit-- failed because of bad owner", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeExpiryLimit(duration.days(15), { from: account_temp }), "tx revert -> failed because of bad owner" ); }); it("Should able to change the ExpiryLimit-- failed because expirylimit is less than 1 day", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeExpiryLimit(duration.minutes(50), { from: account_polymath }), "tx revert -> failed because expirylimit is less than 1 day" ); @@ -886,14 +904,14 @@ contract("SecurityTokenRegistry", accounts => { describe("Test cases for the changeTickerRegistrationFee()", async () => { it("Should able to change the TickerRegFee-- failed because of bad owner", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("500"), { from: account_temp }), "tx revert -> failed because of bad owner" ); }); it("Should able to change the TickerRegFee-- failed because of putting the same fee", async () => { - catchRevert( + await catchRevert( I_STRProxied.changeTickerRegistrationFee(initRegFee, { from: account_polymath }), "tx revert -> failed because of putting the same fee" ); @@ -908,7 +926,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail to register the ticker with the old fee", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - catchRevert( + await catchRevert( I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from: token_owner }), "tx revert -> failed because of ticker registeration fee gets change" ); @@ -924,7 +942,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail to launch the securityToken with the old launch fee", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - catchRevert( + await catchRevert( I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }), "tx revert -> failed because of old launch fee" ); @@ -941,21 +959,21 @@ contract("SecurityTokenRegistry", accounts => { describe("Test cases for getters", async () => { it("Should get the security token address", async () => { - let address = await I_STRProxied.getSecurityTokenAddress.call(symbol); + let address = await I_Getter.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); + let data = await I_Getter.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); + let tickersList = await I_Getter.getTickersByOwner.call(token_owner); console.log(tickersList); assert.equal(tickersList.length, 4); - let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + let tickersListArray = await I_Getter.getTickersByOwner.call(account_temp); console.log(tickersListArray); assert.equal(tickersListArray.length, 3); }); @@ -963,14 +981,14 @@ contract("SecurityTokenRegistry", accounts => { describe("Test case for the Removing the ticker", async () => { it("Should remove the ticker from the polymath ecosystem -- bad owner", async () => { - catchRevert( + await catchRevert( I_STRProxied.removeTicker(symbol2, { from: account_investor1 }), "tx revert -> failed because msg.sender should be account_polymath" ); }); it("Should remove the ticker from the polymath ecosystem -- fail because ticker doesn't exist in the ecosystem", async () => { - catchRevert( + await catchRevert( I_STRProxied.removeTicker("HOLA", { from: account_polymath }), "tx revert -> failed because ticker doesn't exist in the polymath ecosystem" ); @@ -989,7 +1007,7 @@ contract("SecurityTokenRegistry", accounts => { 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.toUtf8(x))); + console.log((await I_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(x))); }); it("Should register the ticker 2", async () => { @@ -998,7 +1016,7 @@ contract("SecurityTokenRegistry", accounts => { 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.toUtf8(x))); + console.log((await I_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(x))); }); it("Should register the ticker 3", async () => { @@ -1007,13 +1025,13 @@ contract("SecurityTokenRegistry", accounts => { 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.toUtf8(x))); + console.log((await I_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(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.toUtf8(x))); + console.log((await I_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(x))); }); it("Should modify ticker 1", async () => { @@ -1029,7 +1047,7 @@ contract("SecurityTokenRegistry", accounts => { 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.toUtf8(x))); + console.log((await I_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(x))); }); it("Should modify ticker 3", async () => { @@ -1045,108 +1063,108 @@ contract("SecurityTokenRegistry", accounts => { 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.toUtf8(x))); + console.log((await I_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(x))); }); }); describe("Test cases for IRegistry functionality", async () => { describe("Test cases for reclaiming funds", async () => { - // it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { - // I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); - // catchRevert( - // I_STRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) - // ); - // }); - - // it("Should successfully reclaim POLY tokens -- not authorised", async() => { - // catchRevert( - // I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) - // ); - // }); - - // it("Should successfully reclaim POLY tokens", async () => { - // let bal1 = await I_PolyToken.balanceOf.call(account_polymath); - // await I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_polymath }); - // 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 () => { - // catchRevert(I_STRProxied.pause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); - // }); - - // 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 () => { - // catchRevert(I_STRProxied.unpause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); - // }); - - // 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); - // }); - // }); - - // describe("Test cases for the setProtocolVersion", async() => { - - // it("Should successfully change the protocolVersion -- failed because of bad owner", async() => { - // catchRevert( - // I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp }) - // ); - // }); + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { + I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); + await catchRevert( + I_STRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) + ); + }); + + it("Should successfully reclaim POLY tokens -- not authorised", async() => { + await catchRevert( + I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) + ); + }); + + it("Should successfully reclaim POLY tokens", async () => { + let bal1 = await I_PolyToken.balanceOf.call(account_polymath); + await I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_polymath }); + 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 () => { + await catchRevert(I_STRProxied.pause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); + }); + + 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 () => { + await catchRevert(I_STRProxied.unpause({ from: account_temp }), "tx revert -> msg.sender should be account_polymath"); + }); + + 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); + }); + }); + + describe("Test cases for the setProtocolVersion", async() => { + + it("Should successfully change the protocolVersion -- failed because of bad owner", async() => { + await catchRevert( + I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp }) + ); + }); - // it("Should successfully change the protocolVersion -- failed because factory address is 0x", async() => { - // catchRevert( - // I_STRProxied.setProtocolVersion("0x000000000000000000000000000000000000000", 5, 6, 7, { from: account_polymath }) - // ); - // }); + it("Should successfully change the protocolVersion -- failed because factory address is 0x", async() => { + await catchRevert( + I_STRProxied.setProtocolVersion("0x000000000000000000000000000000000000000", 5, 6, 7, { from: account_polymath }) + ); + }); - // it("Should successfully change the protocolVersion -- not a valid vesrion", async() => { - // catchRevert( - // I_STRProxied.setProtocolVersion(accounts[8], 0, 0, 0, { from: account_polymath }) - // ); - // }); - - // it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async() => { - // let snap_Id = await takeSnapshot(); - // await I_STRProxied.setProtocolVersion(accounts[8], 2, 3, 1, {from: account_polymath }); - // await catchRevert( - // I_STRProxied.setProtocolVersion(accounts[8], 1, 3, 1, {from: account_polymath }) - // ); - // await revertToSnapshot(snap_Id); - // }); + it("Should successfully change the protocolVersion -- not a valid vesrion", async() => { + await catchRevert( + I_STRProxied.setProtocolVersion(accounts[8], 0, 0, 0, { from: account_polymath }) + ); + }); + + it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async() => { + let snap_Id = await takeSnapshot(); + await I_STRProxied.setProtocolVersion(accounts[8], 2, 3, 1, {from: account_polymath }); + await catchRevert( + I_STRProxied.setProtocolVersion(accounts[8], 1, 3, 1, {from: account_polymath }) + ); + await revertToSnapshot(snap_Id); + }); - // }); - - // describe("Test cases for the transferOwnership", async() => { - - // it("Should fail to transfer the ownership -- not authorised", async() => { - // catchRevert( - // I_STRProxied.transferOwnership(account_temp, { from: account_issuer}) - // ); - // }); - - // it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { - // catchRevert( - // I_STRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) - // ); - // }); - - // it("Should successfully transfer the ownership of the STR", async() => { - // let tx = await I_STRProxied.transferOwnership(account_temp, { from: account_polymath }); - // assert.equal(tx.logs[0].args.previousOwner, account_polymath); - // assert.equal(tx.logs[0].args.newOwner, account_temp); - // }); - // }) - //}); + }); + + describe("Test cases for the transferOwnership", async() => { + + it("Should fail to transfer the ownership -- not authorised", async() => { + await catchRevert( + I_STRProxied.transferOwnership(account_temp, { from: account_issuer}) + ); + }); + + it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { + await catchRevert( + I_STRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) + ); + }); + + it("Should successfully transfer the ownership of the STR", async() => { + let tx = await I_STRProxied.transferOwnership(account_temp, { from: account_polymath }); + assert.equal(tx.logs[0].args.previousOwner, account_polymath); + assert.equal(tx.logs[0].args.newOwner, account_temp); + }); + }) + }); }); diff --git a/test/o_security_token.js b/test/o_security_token.js index a5ce2636f..6ab78db67 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -67,6 +67,7 @@ contract("SecurityToken", accounts => { let I_PolymathRegistry; let I_MockRedemptionManagerFactory; let I_MockRedemptionManager; + let I_STRGetter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -129,7 +130,8 @@ contract("SecurityToken", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 928504634..3bf09d604 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -59,6 +59,7 @@ contract("USDTieredSTO", accounts => { let I_DaiToken; let I_PolymathRegistry; let P_USDTieredSTOFactory; + let I_STRGetter; // SecurityToken Details for funds raise Type ETH const NAME = "Team"; @@ -220,7 +221,8 @@ contract("USDTieredSTO", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 1b58c3e03..cee19785a 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -57,6 +57,7 @@ contract("USDTieredSTO Sim", accounts => { let I_PolyToken; let I_DaiToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details for funds raise Type ETH const NAME = "Team"; @@ -193,7 +194,8 @@ contract("USDTieredSTO Sim", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 222db8a0d..0c4a06add 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -45,6 +45,7 @@ contract("Concurrent STO", accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // STO instance declaration let I_CappedSTOFactory; @@ -92,7 +93,8 @@ contract("Concurrent STO", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the STO Factories diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index 3b5b58c3c..ca99abaa8 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -68,6 +68,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { let I_MRProxied; let I_STRProxied; let I_STRProxiedNew; + let I_STRGetter; let I_SecurityTokenRegistry; //let I_UpgradedSecurityTokenRegistry @@ -114,7 +115,8 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 4: Deploy the GeneralDelegateManagerFactory diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 5db222274..ab796edf3 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -9,6 +9,7 @@ const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock const OwnedUpgradeabilityProxy = artifacts.require("./OwnedUpgradeabilityProxy.sol"); const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const STRGetter = artifacts.require("./STRGetter.sol"); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -28,6 +29,8 @@ contract("SecurityTokenRegistryProxy", accounts => { let I_SecurityToken; let I_ModuleRegistry; let I_FeatureRegistry; + let I_STRGetter; + let I_Getter; let account_polymath; let account_temp; @@ -46,7 +49,7 @@ contract("SecurityTokenRegistryProxy", accounts => { const decimals = 18; const transferManagerKey = 2; - const STRProxyParameters = ["address", "address", "uint256", "uint256", "address"]; + const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; async function readStorage(contractAddress, slot) { return await web3.eth.getStorageAt(contractAddress, slot); @@ -72,7 +75,8 @@ contract("SecurityTokenRegistryProxy", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ from: account_polymath }); @@ -105,7 +109,8 @@ contract("SecurityTokenRegistryProxy", accounts => { I_STFactory.address, initRegFee, initRegFee, - account_polymath + account_polymath, + I_STRGetter.address ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath @@ -205,13 +210,15 @@ contract("SecurityTokenRegistryProxy", accounts => { ); assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address, "Implemnted address is not matched"); I_STRProxied = await SecurityTokenRegistryMock.at(I_SecurityTokenRegistryProxy.address); + I_Getter = await STRGetter.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); + + let _tokenAddress = await I_Getter.getSecurityTokenAddress.call(symbol); + let _data = await I_Getter.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"); @@ -219,7 +226,7 @@ contract("SecurityTokenRegistryProxy", accounts => { 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); + let _tokenAddress = await I_Getter.getSecurityTokenAddress.call(symbol); assert.equal(_tokenAddress, account_temp, "Should match with the changed address"); }); }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 91b578a9d..88a22af93 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -34,6 +34,7 @@ contract("ModuleRegistryProxy", accounts => { let I_SecurityToken; let I_ModuleRegistry; let I_FeatureRegistry; + let I_STRGetter; let account_polymath; let account_temp; @@ -78,7 +79,8 @@ contract("ModuleRegistryProxy", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: account_polymath}); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 9e664b1c5..5059388a0 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -52,6 +52,7 @@ contract("TrackedRedemption", accounts => { let I_MRProxied; let I_PolymathRegistry; let P_TrackedRedemptionFactory; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -99,7 +100,8 @@ contract("TrackedRedemption", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 9dfccbec8..00419b1d8 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -51,6 +51,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter // SecurityToken Details const name = "Team"; @@ -91,7 +92,8 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 4(c): Deploy the VolumeRestrictionTransferManager diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index a1b828fb1..4829eec5f 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -48,6 +48,7 @@ contract('ScheduledCheckpoint', accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -89,7 +90,8 @@ contract('ScheduledCheckpoint', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 2: Deploy the ScheduleCheckpointModule diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 13865df0a..6bff3ee24 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -77,6 +77,7 @@ contract('GeneralPermissionManager Fuzz', accounts => { let P_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_ManualApprovalTransferManager; + let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -136,7 +137,8 @@ contract('GeneralPermissionManager Fuzz', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory diff --git a/yarn.lock b/yarn.lock index 49520affa..53ce18639 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7378,4 +7378,4 @@ yauzl@^2.4.2: resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" dependencies: buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" + fd-slicer "~1.1.0" \ No newline at end of file From 3d20fcff61d1953782cb1d605b199da7d340b3ba Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 3 Jan 2019 14:14:24 +0530 Subject: [PATCH 050/119] minor fix --- contracts/SecurityTokenRegistry.sol | 5 +- yarn.lock | 117 +--------------------------- 2 files changed, 5 insertions(+), 117 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 9ce1a9cbb..b3a023a78 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -72,6 +72,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { bytes32 constant PAUSED = 0xee35723ac350a69d2a92d3703f17439cbaadf2f093a21ba5bf5f1a53eb2a14d9; bytes32 constant OWNER = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; bytes32 constant POLYMATHREGISTRY = 0x90eeab7c36075577c7cc5ff366e389fefa8a18289b949bab3529ab4471139d4d; + bytes32 constant STRGETTER = 0x982f24b3bd80807ec3cb227ba152e15c07d66855fa8ae6ca536e689205c0e2e9; // Emit when network becomes paused event Pause(uint256 _timestammp); @@ -191,7 +192,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { set(POLYMATHREGISTRY, _polymathRegistry); _setProtocolVersion(_STFactory, uint8(2), uint8(0), uint8(0)); set(INITIALIZE, true); - set(Encoder.getKey("STRGetter"), _getterContract); + set(STRGETTER, _getterContract); _updateFromRegistry(); } @@ -213,7 +214,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { */ function setGetterRegistry(address _getterContract) public onlyOwner { require(_getterContract != address(0)); - set(Encoder.getKey("STRGetter"), _getterContract); + set(STRGETTER, _getterContract); } function _implementation() internal view returns(address) { diff --git a/yarn.lock b/yarn.lock index 53ce18639..74912abd4 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" @@ -76,7 +73,6 @@ acorn-dynamic-import@^2.0.0: acorn-jsx@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.0.tgz#958584ddb60990c02c97c1bd9d521fce433bb101" - integrity sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg== acorn@^4.0.3: version "4.0.13" @@ -89,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" @@ -124,7 +119,6 @@ ajv@^6.1.0: ajv@^6.5.3: version "6.5.5" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.5.tgz#cf97cdade71c6399a92c6d6c4177381291b781a1" - integrity sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -207,13 +201,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" @@ -232,14 +219,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" @@ -983,7 +962,6 @@ 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" @@ -992,7 +970,6 @@ bignumber.js@^4.0.2: 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" @@ -1374,12 +1351,10 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, 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" @@ -1537,7 +1512,6 @@ colors@^1.1.2: 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" @@ -1701,18 +1675,16 @@ 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" semver "^5.5.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" @@ -1762,14 +1734,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" @@ -1806,10 +1770,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" @@ -2250,7 +2210,6 @@ escope@^3.6.0: 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" @@ -2269,7 +2228,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" @@ -2292,7 +2250,6 @@ eslint-plugin-import@^2.10.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" @@ -2304,17 +2261,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" @@ -2322,7 +2276,6 @@ 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" @@ -2331,7 +2284,6 @@ eslint-visitor-keys@^1.0.0: eslint@^5.8.0: version "5.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.8.0.tgz#91fbf24f6e0471e8fdf681a4d9dd1b2c9f28309b" - integrity sha512-Zok6Bru3y2JprqTNm14mgQ15YQu/SMDkWdnmHfFg770DIUlmMFd/gqqzCHekxzjHZJxXv3tmTpH0C1icaYJsRQ== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.5.3" @@ -2375,7 +2327,6 @@ eslint@^5.8.0: espree@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" - integrity sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w== dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -2627,7 +2578,6 @@ ethereumjs-wallet@^0.6.0: ethers@^4.0.7: version "4.0.9" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.9.tgz#82bb075b1b3da847d672426cb24685371389155d" - integrity sha512-GcPAI8yRCx/Sihk9OCBobERCvjnrLtvCIqJRJUuNUDlR81z9vyRS7siJ3gimPi1JUKMscrFBDOul4ZA9NM0jHA== dependencies: "@types/node" "^10.3.2" aes-js "3.0.0" @@ -2776,18 +2726,6 @@ 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" @@ -2797,7 +2735,6 @@ extendr@^2.1.0: 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" @@ -2846,15 +2783,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" @@ -3066,7 +2994,6 @@ fs.realpath@^1.0.0: 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: version "1.2.4" @@ -3359,7 +3286,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" @@ -3467,12 +3393,10 @@ ignore-walk@^3.0.1: 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" @@ -3519,7 +3443,6 @@ ini@~1.3.0: inquirer@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" - integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -3641,12 +3564,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" @@ -4240,7 +4157,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" @@ -4368,7 +4284,6 @@ 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" @@ -4455,7 +4370,6 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0. 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" @@ -4606,7 +4520,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" @@ -4758,14 +4671,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" @@ -4824,7 +4729,6 @@ onetime@^2.0.0: openzeppelin-solidity@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.0.0.tgz#b45dddbdae090f89577598c1a7e7518df61b7ba2" - integrity sha512-SolpxQFArtiYnlSNg3dZ9sz0WVlKtPqSOcJkXRllaZp4+Lpfqz3vxF0yoh7g75TszKPyadqoJmU7+GM/vwh9SA== optimist@^0.6.1: version "0.6.1" @@ -5381,7 +5285,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpp@^2.0.0, 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" @@ -5577,7 +5480,6 @@ rustbn.js@~0.2.0: 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" @@ -5626,7 +5528,6 @@ 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" @@ -5637,7 +5538,6 @@ scrypt-async@^1.2.0: 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: version "0.2.0" @@ -6110,15 +6010,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" @@ -6249,7 +6140,6 @@ swarm-js@0.1.37: table@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" - integrity sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg== dependencies: ajv "^6.5.3" lodash "^4.17.10" @@ -6462,7 +6352,6 @@ truffle-error@^0.0.3: 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" - integrity sha512-p4dCmB/roQaHaRMe7Ihej4/Cdmq7Usi6aZsPv/cc2x7S5bYLSwwpgQBdjz4PjPSgNh8zqLte6ZhWkkW1CEq1iQ== dependencies: ethereumjs-tx "^1.3.4" ethereumjs-wallet "^0.6.0" @@ -6488,7 +6377,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" @@ -7232,7 +7120,6 @@ 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" @@ -7378,4 +7265,4 @@ yauzl@^2.4.2: resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" dependencies: buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" \ No newline at end of file + fd-slicer "~1.1.0" From 8655f87071320fc3ef2bb4b03589c3fcbd90988d Mon Sep 17 00:00:00 2001 From: Ricko Date: Fri, 4 Jan 2019 02:24:13 +0800 Subject: [PATCH 051/119] Index module added params st (#432) * added indexed params * updated change log * remove types from index * deleted unwanted test --- CHANGELOG.md | 7 +++++++ contracts/tokens/SecurityToken.sol | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd733dd6..58ad6a93a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog All notable changes to this project will be documented in this file. +# v3.0.0 + +[__3.0.0__] + +## Changed +* Changed the first three params in Security Token `event ModuleAdded()` to be indexed for search. Params are `unit8[] types`, `bytes32 _name` and `address _moduleFactory` + # v3.0.0 - Release Candidate [__3.0.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __10-11-18__ diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 298561a2b..f3ecbdaa3 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -85,8 +85,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Emit at the time when module get added event ModuleAdded( uint8[] _types, - bytes32 _name, - address _moduleFactory, + bytes32 indexed _name, + address indexed _moduleFactory, address _module, uint256 _moduleCost, uint256 _budget, From ef2e32ff097e36697e81e8a866c3161ba3268b12 Mon Sep 17 00:00:00 2001 From: Dmitriy Kostin Date: Mon, 7 Jan 2019 17:42:56 +0200 Subject: [PATCH 052/119] Get all created STs (#494) * added getTokens() * added test for getTokens() * changed _getTokens * updated STRGetter after merge * fixed tests --- contracts/STRGetter.sol | 20 ++++++++++++++-- .../interfaces/ISecurityTokenRegistry.sol | 6 +++++ test/n_security_token_registry.js | 24 +++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/contracts/STRGetter.sol b/contracts/STRGetter.sol index 4187e8eb7..c48a0ce8c 100644 --- a/contracts/STRGetter.sol +++ b/contracts/STRGetter.sol @@ -46,6 +46,22 @@ contract STRGetter is EternalStorage { * @dev Intention is that this is called off-chain so block gas limit is not relevant */ function getTokensByOwner(address _owner) external view returns(address[]) { + return _getTokens(false, _owner); + } + + /** + * @notice Returns the list of all tokens + * @dev Intention is that this is called off-chain so block gas limit is not relevant + */ + function getTokens() external view returns(address[]) { + return _getTokens(true, address(0)); + } + /** + * @notice Returns the list of tokens owned by the selected address + * @param _allTokens if _allTokens is true returns all tokens despite on the second parameter + * @param _owner is the address which owns the list of tickers + */ + function _getTokens(bool _allTokens, address _owner) internal view returns(address[]) { // Loop over all active users, then all associated tickers of those users // This ensures we find tokens, even if their owner has been modified address[] memory activeUsers = getArrayAddress(Encoder.getKey("activeUsers")); @@ -59,7 +75,7 @@ contract STRGetter is EternalStorage { for (j = 0; j < tickers.length; j++) { token = getAddress(Encoder.getKey("tickerToSecurityToken", Util.bytes32ToString(tickers[j]))); if (token != address(0)) { - if (IOwnable(token).owner() == _owner) { + if (_allTokens || IOwnable(token).owner() == _owner) { count = count + 1; } } @@ -72,7 +88,7 @@ contract STRGetter is EternalStorage { for (j = 0; j < tickers.length; j++) { token = getAddress(Encoder.getKey("tickerToSecurityToken", Util.bytes32ToString(tickers[j]))); if (token != address(0)) { - if (IOwnable(token).owner() == _owner) { + if (_allTokens || IOwnable(token).owner() == _owner) { result[index] = token; index = index + 1; } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index c7de4646d..1e1c82b49 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -107,6 +107,12 @@ interface ISecurityTokenRegistry { */ function getTokensByOwner(address _owner) external view returns(address[]); + /** + * @notice Returns the list of all tokens + * @dev Intention is that this is called off-chain so block gas limit is not relevant + */ + function getTokens() external view returns(address[]); + /** * @notice Returns the owner and timestamp for a given ticker * @param _ticker ticker diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index e9bca4d07..c8210a786 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -551,6 +551,30 @@ contract("SecurityTokenRegistry", accounts => { await I_STRProxied.generateSecurityToken(name, "CCC", tokenDetails, false, { from: token_owner }), await revertToSnapshot(snap_Id); }); + + it("Should get all created security tokens", async() => { + let snap_Id = await takeSnapshot(); + await I_PolyToken.getTokens(web3.utils.toWei("500"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: account_temp }); + await I_STRProxied.registerTicker(account_temp, "TMP", name, { from: account_temp }); + let tx = await I_STRProxied.generateSecurityToken(name, "TMP", tokenDetails, false, { from: account_temp }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, "TMP", "SecurityToken doesn't get deployed"); + + let securityTokenTmp = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + let tokens = await I_Getter.getTokensByOwner.call(token_owner); + assert.equal(tokens.length, 1); + assert.equal(tokens[0], I_SecurityToken.address); + + let allTokens = await I_Getter.getTokens.call(); + assert.equal(allTokens.length, 2); + assert.equal(allTokens[0], securityTokenTmp.address); + assert.equal(allTokens[1], I_SecurityToken.address); + + await revertToSnapshot(snap_Id); + }); }); describe("Generate SecurityToken v2", async () => { From cd4a7f9451cf127d501be7b68ecf33e3cf94f023 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 9 Jan 2019 18:35:25 +0530 Subject: [PATCH 053/119] Solidity 0.5.0 (#478) * Added truffle next * Added refactor plugin * Capped STO refactor * constant to view * Updated refactor * added storage location to return params * pm fixes * Oraclize fixes * Custom datatype fixes * Updated refactor * PM fixes * Updated Oraclize * wip * It's compiling! * Updated CI config * Updated CI config * Updated circleCI config * Updated circleCI * Updated CircleCI config * Payable address changes * reduced contract size for test * Updated truffle * Deployment fixed * merge refactor * Revert oraclize changes * WIP * Migrations refactoring complete * Prettier * refactor js * wip * Create insctance fixed * Create instance changes * await at * log watch refactor * Getsig fixed * cappedsto init fn fixed * Block number and timestamp fixed * Await at * toWei to BN * Time travel fixed * Time travel changed * wip * Minor fixes * WIP * bug fix * WIP * capped stro tests fixed * Investor details fixed * ST instance name fixed * Checkpoint tests fixed * CTM tests fixed * empty bytes to 0x0 * wip * toNumber to toString * Whitelist changes * ERC20 tests fixed * WIP * Ether dividend tests fixed * Added fixed address * Permissions to hex * GPM tests fixed * gtm tests fixed * Coverage fixed * updated oz * Updated circleCI docker image * updated coverage script * Updated circleci config * Updated travis script * Updated ci scripts * Issuance tests fixed * MATM tests fixed * Module registry tests fixed * percentage tm tests fixed * Presale tests fixed * STR tests fixed * ST tests fixed * fixed z_general_permission_manager_fuzzer.js * fixed y_scheduled_checkpoints.js * fixed v_tracked_redemptions.js * fixed u_module_registry_proxy.js * fixed t_security_token_registry_proxy.js * Updated usd tiered sto tests * fixed r_concurrent_STO.js * simulation WIP * USDTSTO sim fixed * minor cleanup * added tolerance * Tolerance fixed * update version to 0.5.0 * fixed compilation errors * Coverage script fixed * Tests updated * fixed 2_deploy_contracts.js * Tests fixed * time travel updated * STR test fixed * suggested changes * Merge compilation fix * test fixed * STR proxy tests fixed * reformatting * fixed typo * non payable owner * triggering travis * ST optimization * uncommented tests --- .circleci/config.yml | 12 +- .solcover.js | 2 +- .travis.yml | 8 +- contracts/FeatureRegistry.sol | 9 +- contracts/Migrations.sol | 8 +- contracts/ModuleRegistry.sol | 71 +- contracts/Pausable.sol | 5 +- contracts/PolymathRegistry.sol | 10 +- contracts/ReclaimTokens.sol | 3 +- contracts/RegistryUpdater.sol | 5 +- contracts/STRGetter.sol | 27 +- contracts/SecurityTokenRegistry.sol | 112 +- contracts/external/IMedianizer.sol | 9 +- contracts/external/oraclizeAPI.sol | 1638 +++++++------ contracts/helpers/PolyToken.sol | 31 +- contracts/interfaces/IBoot.sol | 5 +- contracts/interfaces/IFeatureRegistry.sol | 5 +- contracts/interfaces/IModule.sol | 7 +- contracts/interfaces/IModuleFactory.sol | 23 +- contracts/interfaces/IModuleRegistry.sol | 13 +- contracts/interfaces/IOracle.sol | 3 +- contracts/interfaces/IOwnable.sol | 5 +- contracts/interfaces/IPoly.sol | 20 +- contracts/interfaces/IPolymathRegistry.sol | 7 +- contracts/interfaces/ISTFactory.sol | 15 +- contracts/interfaces/ISTO.sol | 7 +- contracts/interfaces/ISecurityToken.sol | 97 +- .../interfaces/ISecurityTokenRegistry.sol | 57 +- contracts/interfaces/ITransferManager.sol | 9 +- contracts/interfaces/IUSDTieredSTOProxy.sol | 15 +- contracts/interfaces/TransferManagerEnums.sol | 5 +- .../libraries/BokkyPooBahsDateTimeLibrary.sol | 113 +- contracts/libraries/DecimalMath.sol | 11 +- contracts/libraries/Encoder.sol | 15 +- contracts/libraries/KindMath.sol | 11 +- contracts/libraries/TokenLib.sol | 110 +- contracts/libraries/Util.sol | 27 +- contracts/libraries/VersionUtils.sol | 89 +- contracts/mocks/MockBurnFactory.sol | 20 +- contracts/mocks/MockFactory.sol | 18 +- contracts/mocks/MockModuleRegistry.sol | 6 +- contracts/mocks/MockOracle.sol | 3 +- contracts/mocks/MockPolyOracle.sol | 7 +- contracts/mocks/MockRedemptionManager.sol | 10 +- contracts/mocks/MockWrongTypeFactory.sol | 15 +- contracts/mocks/PolyTokenFaucet.sol | 40 +- contracts/mocks/SecurityTokenRegistryMock.sol | 11 +- contracts/mocks/TestSTOFactory.sol | 17 +- contracts/modules/Burn/IBurn.sol | 2 +- .../modules/Checkpoint/DividendCheckpoint.sol | 56 +- .../Checkpoint/DividendCheckpointStorage.sol | 17 +- .../Checkpoint/ERC20DividendCheckpoint.sol | 111 +- .../ERC20DividendCheckpointFactory.sol | 28 +- .../ERC20DividendCheckpointStorage.sol | 5 +- .../Checkpoint/EtherDividendCheckpoint.sol | 75 +- .../EtherDividendCheckpointFactory.sol | 28 +- contracts/modules/Checkpoint/ICheckpoint.sol | 2 +- .../Experimental/Burn/TrackedRedemption.sol | 13 +- .../Burn/TrackedRedemptionFactory.sol | 27 +- .../Mixed/ScheduledCheckpoint.sol | 47 +- .../Mixed/ScheduledCheckpointFactory.sol | 35 +- .../LockupVolumeRestrictionTM.sol | 103 +- .../LockupVolumeRestrictionTMFactory.sol | 28 +- .../SingleTradeVolumeRestrictionTM.sol | 58 +- .../SingleTradeVolumeRestrictionTMFactory.sol | 25 +- contracts/modules/Module.sol | 21 +- contracts/modules/ModuleFactory.sol | 35 +- contracts/modules/ModuleStorage.sol | 5 +- .../GeneralPermissionManager.sol | 78 +- .../GeneralPermissionManagerFactory.sol | 27 +- .../GeneralPermissionManagerStorage.sol | 2 +- .../PermissionManager/IPermissionManager.sol | 33 +- contracts/modules/STO/CappedSTO.sol | 57 +- contracts/modules/STO/CappedSTOFactory.sol | 33 +- contracts/modules/STO/CappedSTOStorage.sol | 2 +- contracts/modules/STO/DummySTO.sol | 19 +- contracts/modules/STO/DummySTOFactory.sol | 31 +- contracts/modules/STO/DummySTOStorage.sol | 2 +- contracts/modules/STO/PreSaleSTO.sol | 35 +- contracts/modules/STO/PreSaleSTOFactory.sol | 30 +- contracts/modules/STO/PreSaleSTOStorage.sol | 2 +- contracts/modules/STO/STO.sol | 10 +- contracts/modules/STO/STOStorage.sol | 9 +- contracts/modules/STO/USDTieredSTO.sol | 325 ++- contracts/modules/STO/USDTieredSTOFactory.sol | 29 +- contracts/modules/STO/USDTieredSTOStorage.sol | 23 +- .../TransferManager/CountTransferManager.sol | 20 +- .../CountTransferManagerFactory.sol | 29 +- .../CountTransferManagerStorage.sol | 2 +- .../GeneralTransferManager.sol | 82 +- .../GeneralTransferManagerFactory.sol | 35 +- .../GeneralTransferManagerStorage.sol | 5 +- .../ManualApprovalTransferManager.sol | 23 +- .../ManualApprovalTransferManagerFactory.sol | 30 +- .../ManualApprovalTransferManagerStorage.sol | 2 +- .../PercentageTransferManager.sol | 34 +- .../PercentageTransferManagerFactory.sol | 30 +- .../PercentageTransferManagerStorage.sol | 2 +- .../TransferManager/TransferManager.sol | 3 +- contracts/oracles/MakerDAOOracle.sol | 5 +- contracts/oracles/PolyOracle.sol | 28 +- contracts/proxy/CappedSTOProxy.sol | 12 +- contracts/proxy/CountTransferManagerProxy.sol | 12 +- contracts/proxy/DummySTOProxy.sol | 12 +- .../proxy/ERC20DividendCheckpointProxy.sol | 18 +- .../proxy/EtherDividendCheckpointProxy.sol | 18 +- .../proxy/GeneralPermissionManagerProxy.sol | 12 +- .../proxy/GeneralTransferManagerProxy.sol | 18 +- .../ManualApprovalTransferManagerProxy.sol | 12 +- contracts/proxy/ModuleRegistryProxy.sol | 5 +- contracts/proxy/OwnedProxy.sol | 11 +- contracts/proxy/OwnedUpgradeabilityProxy.sol | 21 +- .../proxy/PercentageTransferManagerProxy.sol | 2 +- contracts/proxy/PreSaleSTOProxy.sol | 2 +- contracts/proxy/Proxy.sol | 12 +- .../proxy/SecurityTokenRegistryProxy.sol | 5 +- contracts/proxy/USDTieredSTOProxy.sol | 13 +- contracts/proxy/UpgradeabilityProxy.sol | 7 +- contracts/storage/EternalStorage.sol | 55 +- contracts/tokens/STFactory.sol | 26 +- contracts/tokens/SecurityToken.sol | 199 +- migrations/1_deploy_token.js | 15 +- migrations/2_deploy_contracts.js | 790 +++--- package.json | 11 +- scripts/calculateSize.js | 20 +- scripts/compareStorageLayout.js | 211 +- scripts/encoders/encode_CappedSTO.js | 75 +- scripts/patch.js | 43 +- scripts/test.sh | 3 +- scripts/tokenInfo-v1.js | 72 +- scripts/tokenInfo-v2.js | 74 +- test/a_poly_oracle.js | 87 +- test/b_capped_sto.js | 449 ++-- test/c_checkpoints.js | 113 +- test/d_count_transfer_manager.js | 247 +- test/e_erc20_dividends.js | 622 +++-- test/f_ether_dividends.js | 603 +++-- test/g_general_permission_manager.js | 256 +- test/h_general_transfer_manager.js | 373 ++- test/helpers/contracts/PolyToken.sol | 6 +- test/helpers/createInstances.js | 145 +- test/helpers/latestTime.js | 9 +- test/helpers/signData.js | 4 +- test/helpers/time.js | 89 +- test/helpers/utils.js | 24 +- test/i_Issuance.js | 94 +- test/j_manual_approval_transfer_manager.js | 181 +- test/k_module_registry.js | 204 +- test/l_percentage_transfer_manager.js | 189 +- test/m_presale_sto.js | 131 +- test/n_security_token_registry.js | 280 +-- test/o_security_token.js | 405 ++- test/p_usd_tiered_sto.js | 2183 +++++++++-------- test/q_usd_tiered_sto_sim.js | 522 ++-- test/r_concurrent_STO.js | 57 +- test/s_v130_to_v140_upgrade.js | 94 +- test/t_security_token_registry_proxy.js | 50 +- test/u_module_registry_proxy.js | 41 +- test/v_tracked_redemptions.js | 76 +- ...kup_volume_restriction_transfer_manager.js | 627 +++-- test/y_scheduled_checkpoints.js | 267 +- test/z_general_permission_manager_fuzzer.js | 573 +++-- truffle-ci.js | 15 +- truffle-config.js | 17 +- upgrade.js | 19 + yarn.lock | 1702 ++++++++++--- 166 files changed, 9308 insertions(+), 7796 deletions(-) create mode 100644 upgrade.js diff --git a/.circleci/config.yml b/.circleci/config.yml index a39d287a0..8bd70f869 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,13 +2,12 @@ version: 2 jobs: build: docker: - - image: circleci/node:8 + - image: maxsam4/solidity-kit 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: truffle compile @@ -18,14 +17,13 @@ jobs: - node_modules test: docker: - - image: circleci/node:8 + - image: maxsam4/solidity-kit parallelism: 2 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: npm run test @@ -39,13 +37,12 @@ jobs: path: ./test-results/mocha/results.xml coverage: docker: - - image: circleci/node:8 + - image: maxsam4/solidity-kit 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: @@ -59,13 +56,12 @@ jobs: path: ./coverage/lcov.info docs: docker: - - image: circleci/node:8 + - image: maxsam4/solidity-kit 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: npm run docs diff --git a/.solcover.js b/.solcover.js index dac86d6e3..2e5750f8d 100644 --- a/.solcover.js +++ b/.solcover.js @@ -5,5 +5,5 @@ module.exports = { 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', 'libraries/BokkyPooBahsDateTimeLibrary.sol', 'storage', 'modules/Experimental'], - forceParse: ['mocks', 'oracles', 'modules/Experimental'] + forceParse: ['mocks', 'oracles', 'helpers', 'modules/Experimental'] }; diff --git a/.travis.yml b/.travis.yml index b676c5840..f5f910f50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,13 @@ cache: - node_modules jobs: include: - - stage: test + - stage: Test + install: + - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum + - sudo apt-get update + - sudo apt-get install -y dpkg + - sudo apt-get install -y solc + - yarn install before_script: truffle version script: npm run test notifications: diff --git a/contracts/FeatureRegistry.sol b/contracts/FeatureRegistry.sol index 936a19976..1fbbb2134 100644 --- a/contracts/FeatureRegistry.sol +++ b/contracts/FeatureRegistry.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ReclaimTokens.sol"; import "./interfaces/IFeatureRegistry.sol"; @@ -7,8 +7,7 @@ import "./interfaces/IFeatureRegistry.sol"; * @title Registry for managing polymath feature switches */ contract FeatureRegistry is IFeatureRegistry, ReclaimTokens { - - mapping (bytes32 => bool) public featureStatus; + mapping(bytes32 => bool) public featureStatus; event ChangeFeatureStatus(string _nameKey, bool _newStatus); @@ -17,7 +16,7 @@ contract FeatureRegistry is IFeatureRegistry, ReclaimTokens { * @param _nameKey is the key for the feature status mapping * @return bool */ - function getFeatureStatus(string _nameKey) external view returns(bool) { + function getFeatureStatus(string calldata _nameKey) external view returns(bool) { bytes32 key = keccak256(bytes(_nameKey)); return featureStatus[key]; } @@ -28,7 +27,7 @@ contract FeatureRegistry is IFeatureRegistry, ReclaimTokens { * @param _nameKey is the key for the feature status mapping * @param _newStatus is the new feature status */ - function setFeatureStatus(string _nameKey, bool _newStatus) public onlyOwner { + function setFeatureStatus(string calldata _nameKey, bool _newStatus) external onlyOwner { bytes32 key = keccak256(bytes(_nameKey)); require(featureStatus[key] != _newStatus, "Status unchanged"); emit ChangeFeatureStatus(_nameKey, _newStatus); diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index 9f2b50b60..a15e3c71b 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,8 +1,6 @@ -pragma solidity ^0.4.24; - +pragma solidity ^0.5.0; contract Migrations { - address public owner; uint public lastCompletedMigration; @@ -16,11 +14,11 @@ contract Migrations { owner = msg.sender; } - function setCompleted(uint _completed)public restricted { + function setCompleted(uint _completed) public restricted { lastCompletedMigration = _completed; } - function upgrade(address _newAddress)public restricted { + function upgrade(address _newAddress) public restricted { Migrations upgraded = Migrations(_newAddress); upgraded.setCompleted(lastCompletedMigration); } diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index f03a360a9..5c538d583 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IModuleRegistry.sol"; @@ -41,7 +41,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // Emit when network becomes paused event Pause(uint256 _timestammp); - // Emit when network becomes unpaused + // Emit when network becomes unpaused event Unpause(uint256 _timestamp); // Emit when Module is used by the SecurityToken event ModuleUsed(address indexed _moduleFactory, address indexed _securityToken); @@ -62,7 +62,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { - require(msg.sender == owner(),"sender must be owner"); + require(msg.sender == owner(), "sender must be owner"); _; } @@ -70,8 +70,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @notice Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPausedOrOwner() { - if (msg.sender == owner()) - _; + if (msg.sender == owner()) _; else { require(!isPaused(), "Already paused"); _; @@ -99,13 +98,12 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { ///////////////////////////// // Constructor - constructor () public - { + constructor() public { } function initialize(address _polymathRegistry, address _owner) external payable { - require(!getBool(Encoder.getKey("initialised")),"already initialized"); + require(!getBool(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); @@ -124,7 +122,10 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // 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"); + require( + getBool(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"); } @@ -149,7 +150,10 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { */ function registerModule(address _moduleFactory) external whenNotPausedOrOwner { if (IFeatureRegistry(getAddress(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"); + 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"); } @@ -173,7 +177,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint256(getArrayAddress(Encoder.getKey("moduleList", uint256(moduleType))).length) ); pushArray(Encoder.getKey("moduleList", uint256(moduleType)), _moduleFactory); - emit ModuleRegistered (_moduleFactory, IOwnable(_moduleFactory).owner()); + emit ModuleRegistered(_moduleFactory, IOwnable(_moduleFactory).owner()); } /** @@ -232,7 +236,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return list of tags * @return corresponding list of module factories */ - function getTagsByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns(bytes32[], address[]) { + function getTagsByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns(bytes32[] memory, address[] memory) { address[] memory modules = getModulesByTypeAndToken(_moduleType, _securityToken); return _tagsByModules(modules); } @@ -243,7 +247,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return list of tags * @return corresponding list of module factories */ - function getTagsByType(uint8 _moduleType) external view returns(bytes32[], address[]) { + function getTagsByType(uint8 _moduleType) external view returns(bytes32[] memory, address[] memory) { address[] memory modules = getModulesByType(_moduleType); return _tagsByModules(modules); } @@ -254,7 +258,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return list of tags * @return corresponding list of module factories */ - function _tagsByModules(address[] _modules) internal view returns(bytes32[], address[]) { + function _tagsByModules(address[] memory _modules) internal view returns(bytes32[] memory, address[] memory) { uint256 counter = 0; uint256 i; uint256 j; @@ -281,7 +285,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @param _factoryAddress is the address of the module factory * @return address array which contains the list of securityTokens that use that module factory */ - function getReputationByFactory(address _factoryAddress) external view returns(address[]) { + function getReputationByFactory(address _factoryAddress) external view returns(address[] memory) { return getArrayAddress(Encoder.getKey("reputation", _factoryAddress)); } @@ -290,7 +294,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @param _moduleType Type of Module * @return address array that contains the list of addresses of module factory contracts. */ - function getModulesByType(uint8 _moduleType) public view returns(address[]) { + function getModulesByType(uint8 _moduleType) public view returns(address[] memory) { return getArrayAddress(Encoder.getKey("moduleList", uint256(_moduleType))); } @@ -300,37 +304,38 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @param _securityToken is the address of SecurityToken * @return address array that contains the list of available addresses of module factory contracts. */ - function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) public view returns (address[]) { + function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) public view returns(address[] memory) { 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(getAddress(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(_isCompatibleModule(_addressList[i], _securityToken)) - counter++; - } - else if (getBool(Encoder.getKey("verified", _addressList[i]))) { - if(_isCompatibleModule(_addressList[i], _securityToken)) - counter++; + if (IOwnable(_addressList[i]).owner() == IOwnable(_securityToken).owner() || getBool( + Encoder.getKey("verified", _addressList[i]) + )) if (_isCompatibleModule(_addressList[i], _securityToken)) counter++; + } else if (getBool(Encoder.getKey("verified", _addressList[i]))) { + if (_isCompatibleModule(_addressList[i], _securityToken)) counter++; } } address[] memory _tempArray = new address[](counter); 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(_isCompatibleModule(_addressList[j], _securityToken)) { + if (IOwnable(_addressList[j]).owner() == IOwnable(_securityToken).owner() || getBool( + Encoder.getKey("verified", _addressList[j]) + )) { + if (_isCompatibleModule(_addressList[j], _securityToken)) { _tempArray[counter] = _addressList[j]; - counter ++; + counter++; } } - } - else if (getBool(Encoder.getKey("verified", _addressList[j]))) { - if(_isCompatibleModule(_addressList[j], _securityToken)) { + } else if (getBool(Encoder.getKey("verified", _addressList[j]))) { + if (_isCompatibleModule(_addressList[j], _securityToken)) { _tempArray[counter] = _addressList[j]; - counter ++; + counter++; } } } @@ -345,7 +350,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { require(_tokenContract != address(0), "0x address is invalid"); IERC20 token = IERC20(_tokenContract); uint256 balance = token.balanceOf(address(this)); - require(token.transfer(owner(), balance),"token transfer failed"); + require(token.transfer(owner(), balance), "token transfer failed"); } /** diff --git a/contracts/Pausable.sol b/contracts/Pausable.sol index fe4a3ca28..996275e5c 100644 --- a/contracts/Pausable.sol +++ b/contracts/Pausable.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Utility contract to allow pausing and unpausing of certain functions */ contract Pausable { - event Pause(uint256 _timestammp); event Unpause(uint256 _timestamp); @@ -26,7 +25,7 @@ contract Pausable { _; } - /** + /** * @notice Called by the owner to pause, triggers stopped state */ function _pause() internal whenNotPaused { diff --git a/contracts/PolymathRegistry.sol b/contracts/PolymathRegistry.sol index 0d6a6ac92..15e34ff6f 100644 --- a/contracts/PolymathRegistry.sol +++ b/contracts/PolymathRegistry.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ReclaimTokens.sol"; @@ -6,8 +6,7 @@ import "./ReclaimTokens.sol"; * @title Core functionality for registry upgradability */ contract PolymathRegistry is ReclaimTokens { - - mapping (bytes32 => address) public storedAddresses; + mapping(bytes32 => address) public storedAddresses; event ChangeAddress(string _nameKey, address indexed _oldAddress, address indexed _newAddress); @@ -16,7 +15,7 @@ contract PolymathRegistry is ReclaimTokens { * @param _nameKey is the key for the contract address mapping * @return address */ - function getAddress(string _nameKey) external view returns(address) { + function getAddress(string calldata _nameKey) external view returns(address) { bytes32 key = keccak256(bytes(_nameKey)); require(storedAddresses[key] != address(0), "Invalid address key"); return storedAddresses[key]; @@ -27,11 +26,10 @@ contract PolymathRegistry is ReclaimTokens { * @param _nameKey is the key for the contract address mapping * @param _newAddress is the new contract address */ - function changeAddress(string _nameKey, address _newAddress) external onlyOwner { + function changeAddress(string calldata _nameKey, address _newAddress) external onlyOwner { bytes32 key = keccak256(bytes(_nameKey)); emit ChangeAddress(_nameKey, storedAddresses[key], _newAddress); storedAddresses[key] = _newAddress; } - } diff --git a/contracts/ReclaimTokens.sol b/contracts/ReclaimTokens.sol index d1c4516f5..75b8cb192 100644 --- a/contracts/ReclaimTokens.sol +++ b/contracts/ReclaimTokens.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; @@ -7,7 +7,6 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; * @title Utility contract to allow owner to retreive any ERC20 sent to the contract */ contract ReclaimTokens is Ownable { - /** * @notice Reclaim all ERC20Basic compatible tokens * @param _tokenContract The address of the token contract diff --git a/contracts/RegistryUpdater.sol b/contracts/RegistryUpdater.sol index ee325b1cf..70e6c6849 100644 --- a/contracts/RegistryUpdater.sol +++ b/contracts/RegistryUpdater.sol @@ -1,17 +1,16 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "./PolymathRegistry.sol"; contract RegistryUpdater is Ownable { - address public polymathRegistry; address public moduleRegistry; address public securityTokenRegistry; address public featureRegistry; address public polyToken; - constructor (address _polymathRegistry) public { + constructor(address _polymathRegistry) public { require(_polymathRegistry != address(0), "Invalid address"); polymathRegistry = _polymathRegistry; } diff --git a/contracts/STRGetter.sol b/contracts/STRGetter.sol index c48a0ce8c..31df84bdb 100644 --- a/contracts/STRGetter.sol +++ b/contracts/STRGetter.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./storage/EternalStorage.sol"; import "./libraries/Util.sol"; @@ -16,11 +16,12 @@ contract STRGetter is EternalStorage { * @notice Returns the list of tickers owned by the selected address * @param _owner is the address which owns the list of tickers */ - function getTickersByOwner(address _owner) external view returns(bytes32[]) { + function getTickersByOwner(address _owner) external view returns(bytes32[] memory) { uint counter = 0; // accessing the data structure userTotickers[_owner].length bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); - for (uint i = 0; i < tickers.length; i++) { + uint i; + for (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 || getTickerStatus(ticker)) { @@ -30,7 +31,7 @@ contract STRGetter is EternalStorage { bytes32[] memory tempList = new bytes32[](counter); counter = 0; for (i = 0; i < tickers.length; i++) { - ticker = Util.bytes32ToString(tickers[i]); + string memory ticker = Util.bytes32ToString(tickers[i]); /*solium-disable-next-line security/no-block-members*/ if (getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || getTickerStatus(ticker)) { tempList[counter] = tickers[i]; @@ -45,7 +46,7 @@ contract STRGetter is EternalStorage { * @param _owner is the address which owns the list of tickers * @dev Intention is that this is called off-chain so block gas limit is not relevant */ - function getTokensByOwner(address _owner) external view returns(address[]) { + function getTokensByOwner(address _owner) external view returns(address[] memory) { return _getTokens(false, _owner); } @@ -53,7 +54,7 @@ contract STRGetter is EternalStorage { * @notice Returns the list of all tokens * @dev Intention is that this is called off-chain so block gas limit is not relevant */ - function getTokens() external view returns(address[]) { + function getTokens() external view returns(address[] memory) { return _getTokens(true, address(0)); } /** @@ -61,7 +62,7 @@ contract STRGetter is EternalStorage { * @param _allTokens if _allTokens is true returns all tokens despite on the second parameter * @param _owner is the address which owns the list of tickers */ - function _getTokens(bool _allTokens, address _owner) internal view returns(address[]) { + function _getTokens(bool _allTokens, address _owner) internal view returns(address[] memory) { // Loop over all active users, then all associated tickers of those users // This ensures we find tokens, even if their owner has been modified address[] memory activeUsers = getArrayAddress(Encoder.getKey("activeUsers")); @@ -107,7 +108,7 @@ contract STRGetter is EternalStorage { * @return string * @return bool */ - function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool) { + function getTickerDetails(string calldata _ticker) external view returns (address, uint256, uint256, string memory, bool) { string memory ticker = Util.upper(_ticker); bool tickerStatus = getTickerStatus(ticker); uint256 expiryDate = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); @@ -131,7 +132,7 @@ contract STRGetter is EternalStorage { * @param _ticker is the ticker of the security token * @return address */ - function getSecurityTokenAddress(string _ticker) external view returns (address) { + function getSecurityTokenAddress(string calldata _ticker) external view returns (address) { string memory ticker = Util.upper(_ticker); return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); } @@ -144,7 +145,7 @@ contract STRGetter is EternalStorage { * @return string is the details of the security token. * @return uint256 is the timestamp at which security Token was deployed. */ - function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256) { + function getSecurityTokenData(address _securityToken) external view returns (string memory, address, string memory, uint256) { return ( getString(Encoder.getKey("securityTokens_ticker", _securityToken)), IOwnable(_securityToken).owner(), @@ -163,7 +164,7 @@ contract STRGetter is EternalStorage { /** * @notice Gets Protocol version */ - function getProtocolVersion() public view returns(uint8[]) { + function getProtocolVersion() public view returns(uint8[] memory) { return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); } @@ -196,7 +197,7 @@ contract STRGetter is EternalStorage { * @param _ticker Ticker whose status need to determine * @return bool */ - function getTickerStatus(string _ticker) public view returns(bool) { + function getTickerStatus(string memory _ticker) public view returns(bool) { return getBool(Encoder.getKey("registeredTickers_status", _ticker)); } @@ -205,7 +206,7 @@ contract STRGetter is EternalStorage { * @param _ticker Ticker whose owner need to determine * @return address Address of the owner */ - function getTickerOwner(string _ticker) public view returns(address) { + function getTickerOwner(string memory _ticker) public view returns(address) { return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index b3a023a78..f8f6e010b 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; @@ -76,13 +76,13 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { // Emit when network becomes paused event Pause(uint256 _timestammp); - // Emit when network becomes unpaused + // Emit when network becomes unpaused event Unpause(uint256 _timestamp); // Emit when the ticker is removed from the registry event TickerRemoved(string _ticker, uint256 _removedAt, address _removedBy); // Emit when the token ticker expiry is changed event ChangeExpiryLimit(uint256 _oldExpiry, uint256 _newExpiry); - // Emit when changeSecurityLaunchFee is called + // Emit when changeSecurityLaunchFee is called event ChangeSecurityLaunchFee(uint256 _oldFee, uint256 _newFee); // Emit when changeTickerRegistrationFee is called event ChangeTickerRegistrationFee(uint256 _oldFee, uint256 _newFee); @@ -120,7 +120,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { - require(msg.sender == owner(),"sender must be owner"); + require(msg.sender == owner(), "sender must be owner"); _; } @@ -128,8 +128,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @notice Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPausedOrOwner() { - if (msg.sender == owner()) - _; + if (msg.sender == owner()) _; else { require(!isPaused(), "Already paused"); _; @@ -144,7 +143,6 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _; } - /** * @notice Modifier to make a function callable only when the contract is paused. */ @@ -153,7 +151,6 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _; } - ///////////////////////////// // Initialization ///////////////////////////// @@ -233,7 +230,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _ticker is unique token ticker * @param _tokenName is the name of the token */ - function registerTicker(address _owner, string _ticker, string _tokenName) external whenNotPausedOrOwner { + function registerTicker(address _owner, string calldata _ticker, string calldata _tokenName) external whenNotPausedOrOwner { require(_owner != address(0), "Owner should not be 0x"); require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); // Attempt to charge the reg fee if it is > 0 POLY @@ -255,13 +252,13 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @notice Internal - Sets the details of the ticker */ function _addTicker( - address _owner, - string _ticker, - string _tokenName, - uint256 _registrationDate, - uint256 _expiryDate, - bool _status, - bool _fromAdmin, + address _owner, + string memory _ticker, + string memory _tokenName, + uint256 _registrationDate, + uint256 _expiryDate, + bool _status, + bool _fromAdmin, uint256 _fee ) internal @@ -283,8 +280,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { */ function modifyTicker( address _owner, - string _ticker, - string _tokenName, + string calldata _ticker, + string calldata _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status @@ -305,8 +302,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { */ function _modifyTicker( address _owner, - string _ticker, - string _tokenName, + string memory _ticker, + string memory _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status @@ -327,7 +324,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0)); } - function _tickerOwner(string _ticker) internal view returns(address) { + function _tickerOwner(string memory _ticker) internal view returns(address) { return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); } @@ -335,7 +332,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @notice Removes the ticker details, associated ownership & security token mapping * @param _ticker is the token ticker */ - function removeTicker(string _ticker) external onlyOwner { + function removeTicker(string calldata _ticker) external onlyOwner { string memory ticker = Util.upper(_ticker); address owner = _tickerOwner(ticker); require(owner != address(0), "Ticker doesn't exist"); @@ -351,18 +348,17 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _ticker is the token ticker * @return bool */ - function _tickerAvailable(string _ticker) internal view returns(bool) { + function _tickerAvailable(string memory _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 - return false; + } else return false; } return true; } - function _tickerStatus(string _ticker) internal view returns(bool) { + function _tickerStatus(string memory _ticker) internal view returns(bool) { return getBool(Encoder.getKey("registeredTickers_status", _ticker)); } @@ -371,7 +367,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _owner is the address of the owner of the ticker * @param _ticker is the ticker symbol */ - function _setTickerOwnership(address _owner, string _ticker) internal { + function _setTickerOwnership(address _owner, string memory _ticker) internal { bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); uint256 length = uint256(getArrayBytes32(_ownerKey).length); pushArray(_ownerKey, Util.stringToBytes32(_ticker)); @@ -387,30 +383,25 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @notice Internal - Stores the ticker details */ function _storeTickerDetails( - string _ticker, + string memory _ticker, address _owner, uint256 _registrationDate, uint256 _expiryDate, - string _tokenName, + string memory _tokenName, bool _status ) internal { bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); - if (getAddress(key) != _owner) - set(key, _owner); + if (getAddress(key) != _owner) set(key, _owner); key = Encoder.getKey("registeredTickers_registrationDate", _ticker); - if (getUint(key) != _registrationDate) - set(key, _registrationDate); + if (getUint(key) != _registrationDate) set(key, _registrationDate); key = Encoder.getKey("registeredTickers_expiryDate", _ticker); - if (getUint(key) != _expiryDate) - set(key, _expiryDate); + if (getUint(key) != _expiryDate) set(key, _expiryDate); key = Encoder.getKey("registeredTickers_tokenName", _ticker); - if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) - set(key, _tokenName); + if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) set(key, _tokenName); key = Encoder.getKey("registeredTickers_status", _ticker); - if (getBool(key) != _status) - set(key, _status); + if (getBool(key) != _status) set(key, _status); } /** @@ -418,13 +409,15 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _newOwner is the address of the new owner of the ticker * @param _ticker is the ticker symbol */ - function transferTickerOwnership(address _newOwner, string _ticker) external whenNotPausedOrOwner { + function transferTickerOwnership(address _newOwner, string calldata _ticker) external whenNotPausedOrOwner { 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"); - if (_tickerStatus(ticker)) - require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); + if (_tickerStatus(ticker)) require( + IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, + "New owner does not match token owner" + ); _deleteTickerOwnership(msg.sender, ticker); _setTickerOwnership(_newOwner, ticker); set(ownerKey, _newOwner); @@ -434,7 +427,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { /** * @notice Internal - Removes the owner of a ticker */ - function _deleteTickerOwnership(address _owner, string _ticker) internal { + function _deleteTickerOwnership(address _owner, string memory _ticker) internal { uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); bytes32[] memory tickers = getArrayBytes32(ownerKey); @@ -468,7 +461,15 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _tokenDetails is the off-chain details of the token * @param _divisible is whether or not the token is divisible */ - function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external whenNotPausedOrOwner { + function generateSecurityToken( + string calldata _name, + string calldata _ticker, + string calldata _tokenDetails, + bool _divisible + ) + external + whenNotPausedOrOwner + { 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); @@ -509,15 +510,15 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _deployedAt is the timestamp at which the security token is deployed */ function modifySecurityToken( - string _name, - string _ticker, + string calldata _name, + string calldata _ticker, address _owner, address _securityToken, - string _tokenDetails, + string calldata _tokenDetails, uint256 _deployedAt - ) - external - onlyOwner + ) + external + onlyOwner { require(bytes(_name).length > 0 && bytes(_ticker).length > 0, "String length > 0"); require(bytes(_ticker).length <= 10, "Ticker length range (0,10]"); @@ -540,7 +541,12 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { /** * @notice Internal - Stores the security token details */ - function _storeSecurityTokenData(address _securityToken, string _ticker, string _tokenDetails, uint256 _deployedAt) internal { + function _storeSecurityTokenData( + address _securityToken, + string memory _ticker, + string memory _tokenDetails, + uint256 _deployedAt + ) internal { set(Encoder.getKey("securityTokens_ticker", _securityToken), _ticker); set(Encoder.getKey("securityTokens_tokenDetails", _securityToken), _tokenDetails); set(Encoder.getKey("securityTokens_deployedAt", _securityToken), _deployedAt); @@ -551,7 +557,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @param _securityToken is the address of the security token * @return bool */ - function isSecurityToken(address _securityToken) external view returns (bool) { + function isSecurityToken(address _securityToken) external view returns(bool) { return (keccak256(bytes(getString(Encoder.getKey("securityTokens_ticker", _securityToken)))) != keccak256("")); } @@ -598,7 +604,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { set(TICKERREGFEE, _tickerRegFee); } - /** + /** * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) */ diff --git a/contracts/external/IMedianizer.sol b/contracts/external/IMedianizer.sol index 755d54a0f..aebe8f77a 100644 --- a/contracts/external/IMedianizer.sol +++ b/contracts/external/IMedianizer.sol @@ -1,15 +1,14 @@ /* solium-disable */ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface to MakerDAO Medianizer contract */ interface IMedianizer { + function peek() external view returns(bytes32, bool); - function peek() constant external returns (bytes32, bool); - - function read() constant external returns (bytes32); + function read() external view returns(bytes32); function set(address wat) external; @@ -27,7 +26,7 @@ interface IMedianizer { function poke(bytes32) external; - function compute() constant external returns (bytes32, bool); + function compute() external view returns(bytes32, bool); function void() external; diff --git a/contracts/external/oraclizeAPI.sol b/contracts/external/oraclizeAPI.sol index bc8045879..9989144c7 100644 --- a/contracts/external/oraclizeAPI.sol +++ b/contracts/external/oraclizeAPI.sol @@ -1,10 +1,9 @@ -// -// Release targetted at solc 0.4.25 to silence compiler warning/error messages, compatible down to 0.4.22 /* -Copyright (c) 2015-2016 Oraclize SRL -Copyright (c) 2016 Oraclize LTD +ORACLIZE_API +Copyright (c) 2015-2016 Oraclize SRL +Copyright (c) 2016 Oraclize LTD Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -13,13 +12,9 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -27,32 +22,37 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +pragma solidity >= 0.5.0; // Incompatible compiler version - please select a compiler within the stated pragma range, or use a different version of the oraclizeAPI! -// This api is currently targeted at 0.4.22 to 0.4.25 (stable builds), please import oraclizeAPI_pre0.4.sol or oraclizeAPI_0.4 where necessary -/* solium-disable */ -pragma solidity >=0.4.22;// Incompatible compiler version... please select one stated within pragma solidity or use different oraclizeAPI version +// Dummy contract only used to emit to end-user they are using wrong solc +contract solcChecker { +/* INCOMPATIBLE SOLC: import the following instead: "github.com/oraclize/ethereum-api/oraclizeAPI_0.4.sol" */ function f(bytes calldata x) external; +} contract OraclizeI { + address public cbAddress; - function query(uint _timestamp, string _datasource, string _arg) external payable returns (bytes32 _id); - function query_withGasLimit(uint _timestamp, string _datasource, string _arg, uint _gaslimit) external payable returns (bytes32 _id); - function query2(uint _timestamp, string _datasource, string _arg1, string _arg2) public payable returns (bytes32 _id); - function query2_withGasLimit(uint _timestamp, string _datasource, string _arg1, string _arg2, uint _gaslimit) external payable returns (bytes32 _id); - function queryN(uint _timestamp, string _datasource, bytes _argN) public payable returns (bytes32 _id); - function queryN_withGasLimit(uint _timestamp, string _datasource, bytes _argN, uint _gaslimit) external payable returns (bytes32 _id); - function getPrice(string _datasource) public returns (uint _dsprice); - function getPrice(string _datasource, uint gaslimit) public returns (uint _dsprice); + function setProofType(byte _proofType) external; function setCustomGasPrice(uint _gasPrice) external; - function randomDS_getSessionPubKeyHash() external constant returns(bytes32); + function getPrice(string memory _datasource) public returns (uint _dsprice); + function randomDS_getSessionPubKeyHash() external view returns (bytes32 _sessionKeyHash); + function getPrice(string memory _datasource, uint _gasLimit) public returns (uint _dsprice); + function queryN(uint _timestamp, string memory _datasource, bytes memory _argN) public payable returns (bytes32 _id); + function query(uint _timestamp, string calldata _datasource, string calldata _arg) external payable returns (bytes32 _id); + function query2(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2) public payable returns (bytes32 _id); + function query_withGasLimit(uint _timestamp, string calldata _datasource, string calldata _arg, uint _gasLimit) external payable returns (bytes32 _id); + function queryN_withGasLimit(uint _timestamp, string calldata _datasource, bytes calldata _argN, uint _gasLimit) external payable returns (bytes32 _id); + function query2_withGasLimit(uint _timestamp, string calldata _datasource, string calldata _arg1, string calldata _arg2, uint _gasLimit) external payable returns (bytes32 _id); } contract OraclizeAddrResolverI { - function getAddress() public returns (address _addr); + function getAddress() public returns (address _address); } - /* + Begin solidity-cborutils https://github.com/smartcontractkit/solidity-cborutils @@ -78,764 +78,876 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ +*/ library Buffer { + struct buffer { bytes buf; uint capacity; } - function init(buffer memory buf, uint _capacity) internal pure { + function init(buffer memory _buf, uint _capacity) internal pure { uint capacity = _capacity; - if(capacity % 32 != 0) capacity += 32 - (capacity % 32); - // Allocate space for the buffer data - buf.capacity = capacity; + if (capacity % 32 != 0) { + capacity += 32 - (capacity % 32); + } + _buf.capacity = capacity; // Allocate space for the buffer data assembly { let ptr := mload(0x40) - mstore(buf, ptr) + mstore(_buf, ptr) mstore(ptr, 0) mstore(0x40, add(ptr, capacity)) } } - function resize(buffer memory buf, uint capacity) private pure { - bytes memory oldbuf = buf.buf; - init(buf, capacity); - append(buf, oldbuf); + function resize(buffer memory _buf, uint _capacity) private pure { + bytes memory oldbuf = _buf.buf; + init(_buf, _capacity); + append(_buf, oldbuf); } - function max(uint a, uint b) private pure returns(uint) { - if(a > b) { - return a; + function max(uint _a, uint _b) private pure returns (uint _max) { + if (_a > _b) { + return _a; } - return b; + return _b; } - /** - * @dev Appends a byte array to the end of the buffer. Resizes if doing so - * would exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function append(buffer memory buf, bytes data) internal pure returns(buffer memory) { - if(data.length + buf.buf.length > buf.capacity) { - resize(buf, max(buf.capacity, data.length) * 2); + * @dev Appends a byte array to the end of the buffer. Resizes if doing so + * would exceed the capacity of the buffer. + * @param _buf The buffer to append to. + * @param _data The data to append. + * @return The original buffer. + * + */ + function append(buffer memory _buf, bytes memory _data) internal pure returns (buffer memory _buffer) { + if (_data.length + _buf.buf.length > _buf.capacity) { + resize(_buf, max(_buf.capacity, _data.length) * 2); } - uint dest; uint src; - uint len = data.length; + uint len = _data.length; assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Start address = buffer address + buffer length + sizeof(buffer length) - dest := add(add(bufptr, buflen), 32) - // Update buffer length - mstore(bufptr, add(buflen, mload(data))) - src := add(data, 32) - } - - // Copy word-length chunks while possible - for(; len >= 32; len -= 32) { + let bufptr := mload(_buf) // Memory address of the buffer data + let buflen := mload(bufptr) // Length of existing buffer data + dest := add(add(bufptr, buflen), 32) // Start address = buffer address + buffer length + sizeof(buffer length) + mstore(bufptr, add(buflen, mload(_data))) // Update buffer length + src := add(_data, 32) + } + for(; len >= 32; len -= 32) { // Copy word-length chunks while possible assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } - - // Copy remaining bytes - uint mask = 256 ** (32 - len) - 1; + uint mask = 256 ** (32 - len) - 1; // Copy remaining bytes assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } - - return buf; + return _buf; } - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function append(buffer memory buf, uint8 data) internal pure { - if(buf.buf.length + 1 > buf.capacity) { - resize(buf, buf.capacity * 2); + * + * @dev Appends a byte to the end of the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param _buf The buffer to append to. + * @param _data The data to append. + * @return The original buffer. + * + */ + function append(buffer memory _buf, uint8 _data) internal pure { + if (_buf.buf.length + 1 > _buf.capacity) { + resize(_buf, _buf.capacity * 2); } - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Address = buffer address + buffer length + sizeof(buffer length) - let dest := add(add(bufptr, buflen), 32) - mstore8(dest, data) - // Update buffer length - mstore(bufptr, add(buflen, 1)) + let bufptr := mload(_buf) // Memory address of the buffer data + let buflen := mload(bufptr) // Length of existing buffer data + let dest := add(add(bufptr, buflen), 32) // Address = buffer address + buffer length + sizeof(buffer length) + mstore8(dest, _data) + mstore(bufptr, add(buflen, 1)) // Update buffer length } } - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { - if(len + buf.buf.length > buf.capacity) { - resize(buf, max(buf.capacity, len) * 2); - } - - uint mask = 256 ** len - 1; + * + * @dev Appends a byte to the end of the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param _buf The buffer to append to. + * @param _data The data to append. + * @return The original buffer. + * + */ + function appendInt(buffer memory _buf, uint _data, uint _len) internal pure returns (buffer memory _buffer) { + if (_len + _buf.buf.length > _buf.capacity) { + resize(_buf, max(_buf.capacity, _len) * 2); + } + uint mask = 256 ** _len - 1; assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Address = buffer address + buffer length + sizeof(buffer length) + len - let dest := add(add(bufptr, buflen), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length - mstore(bufptr, add(buflen, len)) - } - return buf; + let bufptr := mload(_buf) // Memory address of the buffer data + let buflen := mload(bufptr) // Length of existing buffer data + let dest := add(add(bufptr, buflen), _len) // Address = buffer address + buffer length + sizeof(buffer length) + len + mstore(dest, or(and(mload(dest), not(mask)), _data)) + mstore(bufptr, add(buflen, _len)) // Update buffer length + } + return _buf; } } library CBOR { + using Buffer for Buffer.buffer; uint8 private constant MAJOR_TYPE_INT = 0; - uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; + uint8 private constant MAJOR_TYPE_MAP = 5; uint8 private constant MAJOR_TYPE_BYTES = 2; - uint8 private constant MAJOR_TYPE_STRING = 3; uint8 private constant MAJOR_TYPE_ARRAY = 4; - uint8 private constant MAJOR_TYPE_MAP = 5; + uint8 private constant MAJOR_TYPE_STRING = 3; + uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; - function encodeType(Buffer.buffer memory buf, uint8 major, uint value) private pure { - if(value <= 23) { - buf.append(uint8((major << 5) | value)); - } else if(value <= 0xFF) { - buf.append(uint8((major << 5) | 24)); - buf.appendInt(value, 1); - } else if(value <= 0xFFFF) { - buf.append(uint8((major << 5) | 25)); - buf.appendInt(value, 2); - } else if(value <= 0xFFFFFFFF) { - buf.append(uint8((major << 5) | 26)); - buf.appendInt(value, 4); - } else if(value <= 0xFFFFFFFFFFFFFFFF) { - buf.append(uint8((major << 5) | 27)); - buf.appendInt(value, 8); + function encodeType(Buffer.buffer memory _buf, uint8 _major, uint _value) private pure { + if (_value <= 23) { + _buf.append(uint8((_major << 5) | _value)); + } else if (_value <= 0xFF) { + _buf.append(uint8((_major << 5) | 24)); + _buf.appendInt(_value, 1); + } else if (_value <= 0xFFFF) { + _buf.append(uint8((_major << 5) | 25)); + _buf.appendInt(_value, 2); + } else if (_value <= 0xFFFFFFFF) { + _buf.append(uint8((_major << 5) | 26)); + _buf.appendInt(_value, 4); + } else if (_value <= 0xFFFFFFFFFFFFFFFF) { + _buf.append(uint8((_major << 5) | 27)); + _buf.appendInt(_value, 8); } } - function encodeIndefiniteLengthType(Buffer.buffer memory buf, uint8 major) private pure { - buf.append(uint8((major << 5) | 31)); + function encodeIndefiniteLengthType(Buffer.buffer memory _buf, uint8 _major) private pure { + _buf.append(uint8((_major << 5) | 31)); } - function encodeUInt(Buffer.buffer memory buf, uint value) internal pure { - encodeType(buf, MAJOR_TYPE_INT, value); + function encodeUInt(Buffer.buffer memory _buf, uint _value) internal pure { + encodeType(_buf, MAJOR_TYPE_INT, _value); } - function encodeInt(Buffer.buffer memory buf, int value) internal pure { - if(value >= 0) { - encodeType(buf, MAJOR_TYPE_INT, uint(value)); + function encodeInt(Buffer.buffer memory _buf, int _value) internal pure { + if (_value >= 0) { + encodeType(_buf, MAJOR_TYPE_INT, uint(_value)); } else { - encodeType(buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - value)); + encodeType(_buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - _value)); } } - function encodeBytes(Buffer.buffer memory buf, bytes value) internal pure { - encodeType(buf, MAJOR_TYPE_BYTES, value.length); - buf.append(value); + function encodeBytes(Buffer.buffer memory _buf, bytes memory _value) internal pure { + encodeType(_buf, MAJOR_TYPE_BYTES, _value.length); + _buf.append(_value); } - function encodeString(Buffer.buffer memory buf, string value) internal pure { - encodeType(buf, MAJOR_TYPE_STRING, bytes(value).length); - buf.append(bytes(value)); + function encodeString(Buffer.buffer memory _buf, string memory _value) internal pure { + encodeType(_buf, MAJOR_TYPE_STRING, bytes(_value).length); + _buf.append(bytes(_value)); } - function startArray(Buffer.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); + function startArray(Buffer.buffer memory _buf) internal pure { + encodeIndefiniteLengthType(_buf, MAJOR_TYPE_ARRAY); } - function startMap(Buffer.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); + function startMap(Buffer.buffer memory _buf) internal pure { + encodeIndefiniteLengthType(_buf, MAJOR_TYPE_MAP); } - function endSequence(Buffer.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); + function endSequence(Buffer.buffer memory _buf) internal pure { + encodeIndefiniteLengthType(_buf, MAJOR_TYPE_CONTENT_FREE); } } - /* + End solidity-cborutils - */ +*/ contract usingOraclize { - uint constant day = 60*60*24; - uint constant week = 60*60*24*7; - uint constant month = 60*60*24*30; + + using CBOR for Buffer.buffer; + + OraclizeI oraclize; + OraclizeAddrResolverI OAR; + + uint constant day = 60 * 60 * 24; + uint constant week = 60 * 60 * 24 * 7; + uint constant month = 60 * 60 * 24 * 30; + byte constant proofType_NONE = 0x00; - byte constant proofType_TLSNotary = 0x10; byte constant proofType_Ledger = 0x30; - byte constant proofType_Android = 0x40; byte constant proofType_Native = 0xF0; byte constant proofStorage_IPFS = 0x01; + byte constant proofType_Android = 0x40; + byte constant proofType_TLSNotary = 0x10; + + string oraclize_network_name; uint8 constant networkID_auto = 0; + uint8 constant networkID_morden = 2; uint8 constant networkID_mainnet = 1; uint8 constant networkID_testnet = 2; - uint8 constant networkID_morden = 2; uint8 constant networkID_consensys = 161; - OraclizeAddrResolverI OAR; + mapping(bytes32 => bytes32) oraclize_randomDS_args; + mapping(bytes32 => bool) oraclize_randomDS_sessionKeysHashVerified; - OraclizeI oraclize; modifier oraclizeAPI { - if((address(OAR)==0)||(getCodeSize(address(OAR))==0)) + if ((address(OAR) == address(0)) || (getCodeSize(address(OAR)) == 0)) { oraclize_setNetwork(networkID_auto); - - if(address(oraclize) != OAR.getAddress()) + } + if (address(oraclize) != OAR.getAddress()) { oraclize = OraclizeI(OAR.getAddress()); - + } _; } - modifier coupon(string code){ - oraclize = OraclizeI(OAR.getAddress()); + + modifier oraclize_randomDS_proofVerify(bytes32 _queryId, string memory _result, bytes memory _proof) { + // RandomDS Proof Step 1: The prefix has to match 'LP\x01' (Ledger Proof version 1) + require((_proof[0] == "L") && (_proof[1] == "P") && (uint8(_proof[2]) == uint8(1))); + bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); + require(proofVerified); _; } - function oraclize_setNetwork(uint8 networkID) internal returns(bool){ + function oraclize_setNetwork(uint8 _networkID) internal returns (bool _networkSet) { return oraclize_setNetwork(); - networkID; // silence the warning and remain backwards compatible + _networkID; // silence the warning and remain backwards compatible + } + + function oraclize_setNetworkName(string memory _network_name) internal { + oraclize_network_name = _network_name; } - function oraclize_setNetwork() internal returns(bool){ - if (getCodeSize(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed)>0){ //mainnet + + function oraclize_getNetworkName() internal view returns (string memory _networkName) { + return oraclize_network_name; + } + + function oraclize_setNetwork() internal returns (bool _networkSet) { + if (getCodeSize(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed) > 0) { //mainnet OAR = OraclizeAddrResolverI(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed); oraclize_setNetworkName("eth_mainnet"); return true; } - if (getCodeSize(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1)>0){ //ropsten testnet + if (getCodeSize(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1) > 0) { //ropsten testnet OAR = OraclizeAddrResolverI(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1); oraclize_setNetworkName("eth_ropsten3"); return true; } - if (getCodeSize(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e)>0){ //kovan testnet + if (getCodeSize(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e) > 0) { //kovan testnet OAR = OraclizeAddrResolverI(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e); oraclize_setNetworkName("eth_kovan"); return true; } - if (getCodeSize(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48)>0){ //rinkeby testnet + if (getCodeSize(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48) > 0) { //rinkeby testnet OAR = OraclizeAddrResolverI(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48); oraclize_setNetworkName("eth_rinkeby"); return true; } - if (getCodeSize(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475)>0){ //ethereum-bridge + if (getCodeSize(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475) > 0) { //ethereum-bridge OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475); return true; } - if (getCodeSize(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF)>0){ //ether.camp ide + if (getCodeSize(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF) > 0) { //ether.camp ide OAR = OraclizeAddrResolverI(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF); return true; } - if (getCodeSize(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA)>0){ //browser-solidity + if (getCodeSize(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA) > 0) { //browser-solidity OAR = OraclizeAddrResolverI(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA); return true; } return false; } - function __callback(bytes32 myid, string result) public { - __callback(myid, result, new bytes(0)); + function __callback(bytes32 _myid, string memory _result) public { + __callback(_myid, _result, new bytes(0)); } - function __callback(bytes32 myid, string result, bytes proof) public { + + function __callback(bytes32 _myid, string memory _result, bytes memory _proof) public { return; - // Following should never be reached with a preceding return, however - // this is just a placeholder function, ideally meant to be defined in - // child contract when proofs are used - myid; result; proof; // Silence compiler warnings - oraclize = OraclizeI(0); // Additional compiler silence about making function pure/view. - } - - function oraclize_getPrice(string datasource) oraclizeAPI internal returns (uint){ - return oraclize.getPrice(datasource); - } - - function oraclize_getPrice(string datasource, uint gaslimit) oraclizeAPI internal returns (uint){ - return oraclize.getPrice(datasource, gaslimit); - } - - function oraclize_query(string datasource, string arg) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - return oraclize.query.value(price)(0, datasource, arg); - } - function oraclize_query(uint timestamp, string datasource, string arg) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - return oraclize.query.value(price)(timestamp, datasource, arg); - } - function oraclize_query(uint timestamp, string datasource, string arg, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - return oraclize.query_withGasLimit.value(price)(timestamp, datasource, arg, gaslimit); - } - function oraclize_query(string datasource, string arg, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - return oraclize.query_withGasLimit.value(price)(0, datasource, arg, gaslimit); - } - function oraclize_query(string datasource, string arg1, string arg2) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - return oraclize.query2.value(price)(0, datasource, arg1, arg2); - } - function oraclize_query(uint timestamp, string datasource, string arg1, string arg2) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - return oraclize.query2.value(price)(timestamp, datasource, arg1, arg2); - } - function oraclize_query(uint timestamp, string datasource, string arg1, string arg2, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - return oraclize.query2_withGasLimit.value(price)(timestamp, datasource, arg1, arg2, gaslimit); - } - function oraclize_query(string datasource, string arg1, string arg2, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - return oraclize.query2_withGasLimit.value(price)(0, datasource, arg1, arg2, gaslimit); - } - function oraclize_query(string datasource, string[] argN) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - bytes memory args = stra2cbor(argN); - return oraclize.queryN.value(price)(0, datasource, args); - } - function oraclize_query(uint timestamp, string datasource, string[] argN) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - bytes memory args = stra2cbor(argN); - return oraclize.queryN.value(price)(timestamp, datasource, args); - } - function oraclize_query(uint timestamp, string datasource, string[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - bytes memory args = stra2cbor(argN); - return oraclize.queryN_withGasLimit.value(price)(timestamp, datasource, args, gaslimit); - } - function oraclize_query(string datasource, string[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - bytes memory args = stra2cbor(argN); - return oraclize.queryN_withGasLimit.value(price)(0, datasource, args, gaslimit); - } - function oraclize_query(string datasource, string[1] args) oraclizeAPI internal returns (bytes32 id) { + _myid; _result; _proof; // Silence compiler warnings + } + + function oraclize_getPrice(string memory _datasource) oraclizeAPI internal returns (uint _queryPrice) { + return oraclize.getPrice(_datasource); + } + + function oraclize_getPrice(string memory _datasource, uint _gasLimit) oraclizeAPI internal returns (uint _queryPrice) { + return oraclize.getPrice(_datasource, _gasLimit); + } + + function oraclize_query(string memory _datasource, string memory _arg) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + return oraclize.query.value(price)(0, _datasource, _arg); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + return oraclize.query.value(price)(_timestamp, _datasource, _arg); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource,_gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + return oraclize.query_withGasLimit.value(price)(_timestamp, _datasource, _arg, _gasLimit); + } + + function oraclize_query(string memory _datasource, string memory _arg, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + return oraclize.query_withGasLimit.value(price)(0, _datasource, _arg, _gasLimit); + } + + function oraclize_query(string memory _datasource, string memory _arg1, string memory _arg2) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + return oraclize.query2.value(price)(0, _datasource, _arg1, _arg2); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + return oraclize.query2.value(price)(_timestamp, _datasource, _arg1, _arg2); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + return oraclize.query2_withGasLimit.value(price)(_timestamp, _datasource, _arg1, _arg2, _gasLimit); + } + + function oraclize_query(string memory _datasource, string memory _arg1, string memory _arg2, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + return oraclize.query2_withGasLimit.value(price)(0, _datasource, _arg1, _arg2, _gasLimit); + } + + function oraclize_query(string memory _datasource, string[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + bytes memory args = stra2cbor(_argN); + return oraclize.queryN.value(price)(0, _datasource, args); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + bytes memory args = stra2cbor(_argN); + return oraclize.queryN.value(price)(_timestamp, _datasource, args); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + bytes memory args = stra2cbor(_argN); + return oraclize.queryN_withGasLimit.value(price)(_timestamp, _datasource, args, _gasLimit); + } + + function oraclize_query(string memory _datasource, string[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + bytes memory args = stra2cbor(_argN); + return oraclize.queryN_withGasLimit.value(price)(0, _datasource, args, _gasLimit); + } + + function oraclize_query(string memory _datasource, string[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](1); - dynargs[0] = args[0]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[1] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](1); - dynargs[0] = args[0]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](1); - dynargs[0] = args[0]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, string[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](1); - dynargs[0] = args[0]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[2] args) oraclizeAPI internal returns (bytes32 id) { + function oraclize_query(string memory _datasource, string[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[2] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, string[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[3] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, string[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[3] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, string[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[4] args) oraclizeAPI internal returns (bytes32 id) { + function oraclize_query(string memory _datasource, string[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[4] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, string[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, string[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, string[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, string[5] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, string[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(datasource, dynargs); - } - function oraclize_query(uint timestamp, string datasource, string[5] args) oraclizeAPI internal returns (bytes32 id) { + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_datasource, dynargs); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(timestamp, datasource, dynargs); - } - function oraclize_query(uint timestamp, string datasource, string[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_timestamp, _datasource, dynargs); + } + + function oraclize_query(uint _timestamp, string memory _datasource, string[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); - } - function oraclize_query(string datasource, string[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); + } + + function oraclize_query(string memory _datasource, string[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { string[] memory dynargs = new string[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(datasource, dynargs, gaslimit); - } - function oraclize_query(string datasource, bytes[] argN) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - bytes memory args = ba2cbor(argN); - return oraclize.queryN.value(price)(0, datasource, args); - } - function oraclize_query(uint timestamp, string datasource, bytes[] argN) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource); - if (price > 1 ether + tx.gasprice*200000) return 0; // unexpectedly high price - bytes memory args = ba2cbor(argN); - return oraclize.queryN.value(price)(timestamp, datasource, args); - } - function oraclize_query(uint timestamp, string datasource, bytes[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - bytes memory args = ba2cbor(argN); - return oraclize.queryN_withGasLimit.value(price)(timestamp, datasource, args, gaslimit); - } - function oraclize_query(string datasource, bytes[] argN, uint gaslimit) oraclizeAPI internal returns (bytes32 id){ - uint price = oraclize.getPrice(datasource, gaslimit); - if (price > 1 ether + tx.gasprice*gaslimit) return 0; // unexpectedly high price - bytes memory args = ba2cbor(argN); - return oraclize.queryN_withGasLimit.value(price)(0, datasource, args, gaslimit); - } - function oraclize_query(string datasource, bytes[1] args) oraclizeAPI internal returns (bytes32 id) { + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_datasource, dynargs, _gasLimit); + } + + function oraclize_query(string memory _datasource, bytes[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + bytes memory args = ba2cbor(_argN); + return oraclize.queryN.value(price)(0, _datasource, args); + } + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource); + if (price > 1 ether + tx.gasprice * 200000) { + return 0; // Unexpectedly high price + } + bytes memory args = ba2cbor(_argN); + return oraclize.queryN.value(price)(_timestamp, _datasource, args); + } + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + bytes memory args = ba2cbor(_argN); + return oraclize.queryN_withGasLimit.value(price)(_timestamp, _datasource, args, _gasLimit); + } + + function oraclize_query(string memory _datasource, bytes[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + uint price = oraclize.getPrice(_datasource, _gasLimit); + if (price > 1 ether + tx.gasprice * _gasLimit) { + return 0; // Unexpectedly high price + } + bytes memory args = ba2cbor(_argN); + return oraclize.queryN_withGasLimit.value(price)(0, _datasource, args, _gasLimit); + } + + function oraclize_query(string memory _datasource, bytes[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](1); - dynargs[0] = args[0]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[1] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](1); - dynargs[0] = args[0]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](1); - dynargs[0] = args[0]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[1] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, bytes[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](1); - dynargs[0] = args[0]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[2] args) oraclizeAPI internal returns (bytes32 id) { + function oraclize_query(string memory _datasource, bytes[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[2] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[2] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, bytes[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](2); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[3] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, bytes[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[3] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[3] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, bytes[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](3); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[4] args) oraclizeAPI internal returns (bytes32 id) { + function oraclize_query(string memory _datasource, bytes[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[4] args) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(timestamp, datasource, dynargs); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_query(uint timestamp, string datasource, bytes[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[4] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, bytes[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](4); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_query(string datasource, bytes[5] args) oraclizeAPI internal returns (bytes32 id) { - bytes[] memory dynargs = new bytes[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(datasource, dynargs); - } - function oraclize_query(uint timestamp, string datasource, bytes[5] args) oraclizeAPI internal returns (bytes32 id) { - bytes[] memory dynargs = new bytes[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(timestamp, datasource, dynargs); - } - function oraclize_query(uint timestamp, string datasource, bytes[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + + function oraclize_query(string memory _datasource, bytes[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(timestamp, datasource, dynargs, gaslimit); - } - function oraclize_query(string datasource, bytes[5] args, uint gaslimit) oraclizeAPI internal returns (bytes32 id) { + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_datasource, dynargs); + } + + function oraclize_query(uint _timestamp, string memory _datasource, bytes[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { bytes[] memory dynargs = new bytes[](5); - dynargs[0] = args[0]; - dynargs[1] = args[1]; - dynargs[2] = args[2]; - dynargs[3] = args[3]; - dynargs[4] = args[4]; - return oraclize_query(datasource, dynargs, gaslimit); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_timestamp, _datasource, dynargs); } - function oraclize_cbAddress() oraclizeAPI internal returns (address){ - return oraclize.cbAddress(); + function oraclize_query(uint _timestamp, string memory _datasource, bytes[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + bytes[] memory dynargs = new bytes[](5); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); } - function oraclize_setProof(byte proofP) oraclizeAPI internal { - return oraclize.setProofType(proofP); + + function oraclize_query(string memory _datasource, bytes[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { + bytes[] memory dynargs = new bytes[](5); + dynargs[0] = _args[0]; + dynargs[1] = _args[1]; + dynargs[2] = _args[2]; + dynargs[3] = _args[3]; + dynargs[4] = _args[4]; + return oraclize_query(_datasource, dynargs, _gasLimit); } - function oraclize_setCustomGasPrice(uint gasPrice) oraclizeAPI internal { - return oraclize.setCustomGasPrice(gasPrice); + + function oraclize_setProof(byte _proofP) oraclizeAPI internal { + return oraclize.setProofType(_proofP); } - function oraclize_randomDS_getSessionPubKeyHash() oraclizeAPI internal returns (bytes32){ - return oraclize.randomDS_getSessionPubKeyHash(); + + function oraclize_cbAddress() oraclizeAPI internal returns (address _callbackAddress) { + return oraclize.cbAddress(); } - function getCodeSize(address _addr) view internal returns(uint _size) { + function getCodeSize(address _addr) view internal returns (uint _size) { assembly { _size := extcodesize(_addr) } } - function parseAddr(string _a) internal pure returns (address){ + function oraclize_setCustomGasPrice(uint _gasPrice) oraclizeAPI internal { + return oraclize.setCustomGasPrice(_gasPrice); + } + + function oraclize_randomDS_getSessionPubKeyHash() oraclizeAPI internal returns (bytes32 _sessionKeyHash) { + return oraclize.randomDS_getSessionPubKeyHash(); + } + + function parseAddr(string memory _a) internal pure returns (address _parsedAddress) { bytes memory tmp = bytes(_a); uint160 iaddr = 0; uint160 b1; uint160 b2; - for (uint i=2; i<2+2*20; i+=2){ + for (uint i = 2; i < 2 + 2 * 20; i += 2) { iaddr *= 256; - b1 = uint160(tmp[i]); - b2 = uint160(tmp[i+1]); - if ((b1 >= 97)&&(b1 <= 102)) b1 -= 87; - else if ((b1 >= 65)&&(b1 <= 70)) b1 -= 55; - else if ((b1 >= 48)&&(b1 <= 57)) b1 -= 48; - if ((b2 >= 97)&&(b2 <= 102)) b2 -= 87; - else if ((b2 >= 65)&&(b2 <= 70)) b2 -= 55; - else if ((b2 >= 48)&&(b2 <= 57)) b2 -= 48; - iaddr += (b1*16+b2); + b1 = uint160(uint8(tmp[i])); + b2 = uint160(uint8(tmp[i + 1])); + if ((b1 >= 97) && (b1 <= 102)) { + b1 -= 87; + } else if ((b1 >= 65) && (b1 <= 70)) { + b1 -= 55; + } else if ((b1 >= 48) && (b1 <= 57)) { + b1 -= 48; + } + if ((b2 >= 97) && (b2 <= 102)) { + b2 -= 87; + } else if ((b2 >= 65) && (b2 <= 70)) { + b2 -= 55; + } else if ((b2 >= 48) && (b2 <= 57)) { + b2 -= 48; + } + iaddr += (b1 * 16 + b2); } return address(iaddr); } - function strCompare(string _a, string _b) internal pure returns (int) { + function strCompare(string memory _a, string memory _b) internal pure returns (int _returnCode) { bytes memory a = bytes(_a); bytes memory b = bytes(_b); uint minLength = a.length; - if (b.length < minLength) minLength = b.length; - for (uint i = 0; i < minLength; i ++) - if (a[i] < b[i]) + if (b.length < minLength) { + minLength = b.length; + } + for (uint i = 0; i < minLength; i ++) { + if (a[i] < b[i]) { return -1; - else if (a[i] > b[i]) + } else if (a[i] > b[i]) { return 1; - if (a.length < b.length) + } + } + if (a.length < b.length) { return -1; - else if (a.length > b.length) + } else if (a.length > b.length) { return 1; - else + } else { return 0; + } } - function indexOf(string _haystack, string _needle) internal pure returns (int) { + function indexOf(string memory _haystack, string memory _needle) internal pure returns (int _returnCode) { bytes memory h = bytes(_haystack); bytes memory n = bytes(_needle); - if(h.length < 1 || n.length < 1 || (n.length > h.length)) + if (h.length < 1 || n.length < 1 || (n.length > h.length)) { return -1; - else if(h.length > (2**128 -1)) + } else if (h.length > (2 ** 128 - 1)) { return -1; - else - { + } else { uint subindex = 0; - for (uint i = 0; i < h.length; i ++) - { - if (h[i] == n[0]) - { + for (uint i = 0; i < h.length; i++) { + if (h[i] == n[0]) { subindex = 1; - while(subindex < n.length && (i + subindex) < h.length && h[i + subindex] == n[subindex]) - { + while(subindex < n.length && (i + subindex) < h.length && h[i + subindex] == n[subindex]) { subindex++; } - if(subindex == n.length) + if (subindex == n.length) { return int(i); + } } } return -1; } } - function strConcat(string _a, string _b, string _c, string _d, string _e) internal pure returns (string) { + function strConcat(string memory _a, string memory _b) internal pure returns (string memory _concatenatedString) { + return strConcat(_a, _b, "", "", ""); + } + + function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory _concatenatedString) { + return strConcat(_a, _b, _c, "", ""); + } + + function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory _concatenatedString) { + return strConcat(_a, _b, _c, _d, ""); + } + + function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory _concatenatedString) { bytes memory _ba = bytes(_a); bytes memory _bb = bytes(_b); bytes memory _bc = bytes(_c); @@ -844,115 +956,141 @@ contract usingOraclize { string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); bytes memory babcde = bytes(abcde); uint k = 0; - for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i]; - for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i]; - for (i = 0; i < _bc.length; i++) babcde[k++] = _bc[i]; - for (i = 0; i < _bd.length; i++) babcde[k++] = _bd[i]; - for (i = 0; i < _be.length; i++) babcde[k++] = _be[i]; + uint i = 0; + for (i = 0; i < _ba.length; i++) { + babcde[k++] = _ba[i]; + } + for (i = 0; i < _bb.length; i++) { + babcde[k++] = _bb[i]; + } + for (i = 0; i < _bc.length; i++) { + babcde[k++] = _bc[i]; + } + for (i = 0; i < _bd.length; i++) { + babcde[k++] = _bd[i]; + } + for (i = 0; i < _be.length; i++) { + babcde[k++] = _be[i]; + } return string(babcde); } - function strConcat(string _a, string _b, string _c, string _d) internal pure returns (string) { - return strConcat(_a, _b, _c, _d, ""); - } - - function strConcat(string _a, string _b, string _c) internal pure returns (string) { - return strConcat(_a, _b, _c, "", ""); + function safeParseInt(string memory _a) internal pure returns (uint _parsedInt) { + return safeParseInt(_a, 0); } - function strConcat(string _a, string _b) internal pure returns (string) { - return strConcat(_a, _b, "", "", ""); + function safeParseInt(string memory _a, uint _b) internal pure returns (uint _parsedInt) { + bytes memory bresult = bytes(_a); + uint mint = 0; + bool decimals = false; + for (uint i = 0; i < bresult.length; i++) { + if ((uint(uint8(bresult[i])) >= 48) && (uint(uint8(bresult[i])) <= 57)) { + if (decimals) { + if (_b == 0) break; + else _b--; + } + mint *= 10; + mint += uint(uint8(bresult[i])) - 48; + } else if (uint(uint8(bresult[i])) == 46) { + require(!decimals, 'More than one decimal encountered in string!'); + decimals = true; + } else { + revert("Non-numeral character encountered in string!"); + } + } + if (_b > 0) { + mint *= 10 ** _b; + } + return mint; } - // parseInt - function parseInt(string _a) internal pure returns (uint) { + function parseInt(string memory _a) internal pure returns (uint _parsedInt) { return parseInt(_a, 0); } - // parseInt(parseFloat*10^_b) - function parseInt(string _a, uint _b) internal pure returns (uint) { + function parseInt(string memory _a, uint _b) internal pure returns (uint _parsedInt) { bytes memory bresult = bytes(_a); uint mint = 0; bool decimals = false; - for (uint i=0; i= 48)&&(bresult[i] <= 57)){ - if (decimals){ - if (_b == 0) break; - else _b--; + for (uint i = 0; i < bresult.length; i++) { + if ((uint(uint8(bresult[i])) >= 48) && (uint(uint8(bresult[i])) <= 57)) { + if (decimals) { + if (_b == 0) { + break; + } else { + _b--; + } } mint *= 10; - mint += uint(bresult[i]) - 48; - } else if (bresult[i] == 46) decimals = true; + mint += uint(uint8(bresult[i])) - 48; + } else if (uint(uint8(bresult[i])) == 46) { + decimals = true; + } + } + if (_b > 0) { + mint *= 10 ** _b; } - if (_b > 0) mint *= 10**_b; return mint; } - function uint2str(uint i) internal pure returns (string){ - if (i == 0) return "0"; - uint j = i; + function uint2str(uint _i) internal pure returns (string memory _uintAsString) { + if (_i == 0) { + return "0"; + } + uint j = _i; uint len; - while (j != 0){ + while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; - while (i != 0){ - bstr[k--] = byte(48 + i % 10); - i /= 10; + while (_i != 0) { + bstr[k--] = byte(uint8(48 + _i % 10)); + _i /= 10; } return string(bstr); } - using CBOR for Buffer.buffer; - function stra2cbor(string[] arr) internal pure returns (bytes) { + function stra2cbor(string[] memory _arr) internal pure returns (bytes memory _cborEncoding) { safeMemoryCleaner(); Buffer.buffer memory buf; Buffer.init(buf, 1024); buf.startArray(); - for (uint i = 0; i < arr.length; i++) { - buf.encodeString(arr[i]); + for (uint i = 0; i < _arr.length; i++) { + buf.encodeString(_arr[i]); } buf.endSequence(); return buf.buf; } - function ba2cbor(bytes[] arr) internal pure returns (bytes) { + function ba2cbor(bytes[] memory _arr) internal pure returns (bytes memory _cborEncoding) { safeMemoryCleaner(); Buffer.buffer memory buf; Buffer.init(buf, 1024); buf.startArray(); - for (uint i = 0; i < arr.length; i++) { - buf.encodeBytes(arr[i]); + for (uint i = 0; i < _arr.length; i++) { + buf.encodeBytes(_arr[i]); } buf.endSequence(); return buf.buf; } - string oraclize_network_name; - function oraclize_setNetworkName(string _network_name) internal { - oraclize_network_name = _network_name; - } - - function oraclize_getNetworkName() internal view returns (string) { - return oraclize_network_name; - } - - function oraclize_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32){ + function oraclize_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32 _queryId) { require((_nbytes > 0) && (_nbytes <= 32)); - // Convert from seconds to ledger timer ticks - _delay *= 10; + _delay *= 10; // Convert from seconds to ledger timer ticks bytes memory nbytes = new bytes(1); - nbytes[0] = byte(_nbytes); + nbytes[0] = byte(uint8(_nbytes)); bytes memory unonce = new bytes(32); bytes memory sessionKeyHash = new bytes(32); bytes32 sessionKeyHash_bytes32 = oraclize_randomDS_getSessionPubKeyHash(); assembly { mstore(unonce, 0x20) - // the following variables can be relaxed - // check relaxed random contract under ethereum-examples repo - // for an idea on how to override and replace comit hash vars + /* + The following variables can be relaxed. + Check the relaxed random contract at https://github.com/oraclize/ethereum-examples + for an idea on how to override and replace commit hash variables. + */ mstore(add(unonce, 0x20), xor(blockhash(sub(number, 1)), xor(coinbase, timestamp))) mstore(sessionKeyHash, 0x20) mstore(add(sessionKeyHash, 0x20), sessionKeyHash_bytes32) @@ -961,15 +1099,11 @@ contract usingOraclize { assembly { mstore(add(delay, 0x20), _delay) } - bytes memory delay_bytes8 = new bytes(8); copyBytes(delay, 24, 8, delay_bytes8, 0); - bytes[4] memory args = [unonce, nbytes, sessionKeyHash, delay]; bytes32 queryId = oraclize_query("random", args, _customGasLimit); - bytes memory delay_bytes8_left = new bytes(8); - assembly { let x := mload(add(delay_bytes8, 0x20)) mstore8(add(delay_bytes8_left, 0x27), div(x, 0x100000000000000000000000000000000000000000000000000000000000000)) @@ -980,248 +1114,214 @@ contract usingOraclize { mstore8(add(delay_bytes8_left, 0x22), div(x, 0x10000000000000000000000000000000000000000000000000000)) mstore8(add(delay_bytes8_left, 0x21), div(x, 0x100000000000000000000000000000000000000000000000000)) mstore8(add(delay_bytes8_left, 0x20), div(x, 0x1000000000000000000000000000000000000000000000000)) - } - oraclize_randomDS_setCommitment(queryId, keccak256(abi.encodePacked(delay_bytes8_left, args[1], sha256(args[0]), args[2]))); return queryId; } - function oraclize_randomDS_setCommitment(bytes32 queryId, bytes32 commitment) internal { - oraclize_randomDS_args[queryId] = commitment; + function oraclize_randomDS_setCommitment(bytes32 _queryId, bytes32 _commitment) internal { + oraclize_randomDS_args[_queryId] = _commitment; } - mapping(bytes32=>bytes32) oraclize_randomDS_args; - mapping(bytes32=>bool) oraclize_randomDS_sessionKeysHashVerified; - - function verifySig(bytes32 tosignh, bytes dersig, bytes pubkey) internal returns (bool){ + function verifySig(bytes32 _tosignh, bytes memory _dersig, bytes memory _pubkey) internal returns (bool _sigVerified) { bool sigok; address signer; - bytes32 sigr; bytes32 sigs; - bytes memory sigr_ = new bytes(32); - uint offset = 4+(uint(dersig[3]) - 0x20); - sigr_ = copyBytes(dersig, offset, 32, sigr_, 0); + uint offset = 4 + (uint(uint8(_dersig[3])) - 0x20); + sigr_ = copyBytes(_dersig, offset, 32, sigr_, 0); bytes memory sigs_ = new bytes(32); offset += 32 + 2; - sigs_ = copyBytes(dersig, offset+(uint(dersig[offset-1]) - 0x20), 32, sigs_, 0); - + sigs_ = copyBytes(_dersig, offset + (uint(uint8(_dersig[offset - 1])) - 0x20), 32, sigs_, 0); assembly { sigr := mload(add(sigr_, 32)) sigs := mload(add(sigs_, 32)) } - - - (sigok, signer) = safer_ecrecover(tosignh, 27, sigr, sigs); - if (address(keccak256(pubkey)) == signer) return true; - else { - (sigok, signer) = safer_ecrecover(tosignh, 28, sigr, sigs); - return (address(keccak256(pubkey)) == signer); + (sigok, signer) = safer_ecrecover(_tosignh, 27, sigr, sigs); + if (address(uint160(uint256(keccak256(_pubkey)))) == signer) { + return true; + } else { + (sigok, signer) = safer_ecrecover(_tosignh, 28, sigr, sigs); + return (address(uint160(uint256(keccak256(_pubkey)))) == signer); } } - function oraclize_randomDS_proofVerify__sessionKeyValidity(bytes proof, uint sig2offset) internal returns (bool) { + function oraclize_randomDS_proofVerify__sessionKeyValidity(bytes memory _proof, uint _sig2offset) internal returns (bool _proofVerified) { bool sigok; - - // Step 6: verify the attestation signature, APPKEY1 must sign the sessionKey from the correct ledger app (CODEHASH) - bytes memory sig2 = new bytes(uint(proof[sig2offset+1])+2); - copyBytes(proof, sig2offset, sig2.length, sig2, 0); - + // Random DS Proof Step 6: Verify the attestation signature, APPKEY1 must sign the sessionKey from the correct ledger app (CODEHASH) + bytes memory sig2 = new bytes(uint(uint8(_proof[_sig2offset + 1])) + 2); + copyBytes(_proof, _sig2offset, sig2.length, sig2, 0); bytes memory appkey1_pubkey = new bytes(64); - copyBytes(proof, 3+1, 64, appkey1_pubkey, 0); - - bytes memory tosign2 = new bytes(1+65+32); - tosign2[0] = byte(1); //role - copyBytes(proof, sig2offset-65, 65, tosign2, 1); + copyBytes(_proof, 3 + 1, 64, appkey1_pubkey, 0); + bytes memory tosign2 = new bytes(1 + 65 + 32); + tosign2[0] = byte(uint8(1)); //role + copyBytes(_proof, _sig2offset - 65, 65, tosign2, 1); bytes memory CODEHASH = hex"fd94fa71bc0ba10d39d464d0d8f465efeef0a2764e3887fcc9df41ded20f505c"; - copyBytes(CODEHASH, 0, 32, tosign2, 1+65); + copyBytes(CODEHASH, 0, 32, tosign2, 1 + 65); sigok = verifySig(sha256(tosign2), sig2, appkey1_pubkey); - - if (sigok == false) return false; - - - // Step 7: verify the APPKEY1 provenance (must be signed by Ledger) + if (!sigok) { + return false; + } + // Random DS Proof Step 7: Verify the APPKEY1 provenance (must be signed by Ledger) bytes memory LEDGERKEY = hex"7fb956469c5c9b89840d55b43537e66a98dd4811ea0a27224272c2e5622911e8537a2f8e86a46baec82864e98dd01e9ccc2f8bc5dfc9cbe5a91a290498dd96e4"; - - bytes memory tosign3 = new bytes(1+65); + bytes memory tosign3 = new bytes(1 + 65); tosign3[0] = 0xFE; - copyBytes(proof, 3, 65, tosign3, 1); - - bytes memory sig3 = new bytes(uint(proof[3+65+1])+2); - copyBytes(proof, 3+65, sig3.length, sig3, 0); - + copyBytes(_proof, 3, 65, tosign3, 1); + bytes memory sig3 = new bytes(uint(uint8(_proof[3 + 65 + 1])) + 2); + copyBytes(_proof, 3 + 65, sig3.length, sig3, 0); sigok = verifySig(sha256(tosign3), sig3, LEDGERKEY); - return sigok; } - modifier oraclize_randomDS_proofVerify(bytes32 _queryId, string _result, bytes _proof) { - // Step 1: the prefix has to match 'LP\x01' (Ledger Proof version 1) - require((_proof[0] == "L") && (_proof[1] == "P") && (_proof[2] == 1)); - - bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); - require(proofVerified); - - _; - } - - function oraclize_randomDS_proofVerify__returnCode(bytes32 _queryId, string _result, bytes _proof) internal returns (uint8){ - // Step 1: the prefix has to match 'LP\x01' (Ledger Proof version 1) - if ((_proof[0] != "L")||(_proof[1] != "P")||(_proof[2] != 1)) return 1; - + function oraclize_randomDS_proofVerify__returnCode(bytes32 _queryId, string memory _result, bytes memory _proof) internal returns (uint8 _returnCode) { + // Random DS Proof Step 1: The prefix has to match 'LP\x01' (Ledger Proof version 1) + if ((_proof[0] != "L") || (_proof[1] != "P") || (uint8(_proof[2]) != uint8(1))) { + return 1; + } bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); - if (proofVerified == false) return 2; - + if (!proofVerified) { + return 2; + } return 0; } - function matchBytes32Prefix(bytes32 content, bytes prefix, uint n_random_bytes) internal pure returns (bool){ + function matchBytes32Prefix(bytes32 _content, bytes memory _prefix, uint _nRandomBytes) internal pure returns (bool _matchesPrefix) { bool match_ = true; - - require(prefix.length == n_random_bytes); - - for (uint256 i=0; i< n_random_bytes; i++) { - if (content[i] != prefix[i]) match_ = false; + require(_prefix.length == _nRandomBytes); + for (uint256 i = 0; i< _nRandomBytes; i++) { + if (_content[i] != _prefix[i]) { + match_ = false; + } } - return match_; } - function oraclize_randomDS_proofVerify__main(bytes proof, bytes32 queryId, bytes result, string context_name) internal returns (bool){ - - // Step 2: the unique keyhash has to match with the sha256 of (context name + queryId) - uint ledgerProofLength = 3+65+(uint(proof[3+65+1])+2)+32; + function oraclize_randomDS_proofVerify__main(bytes memory _proof, bytes32 _queryId, bytes memory _result, string memory _contextName) internal returns (bool _proofVerified) { + // Random DS Proof Step 2: The unique keyhash has to match with the sha256 of (context name + _queryId) + uint ledgerProofLength = 3 + 65 + (uint(uint8(_proof[3 + 65 + 1])) + 2) + 32; bytes memory keyhash = new bytes(32); - copyBytes(proof, ledgerProofLength, 32, keyhash, 0); - if (!(keccak256(keyhash) == keccak256(abi.encodePacked(sha256(abi.encodePacked(context_name, queryId)))))) return false; - - bytes memory sig1 = new bytes(uint(proof[ledgerProofLength+(32+8+1+32)+1])+2); - copyBytes(proof, ledgerProofLength+(32+8+1+32), sig1.length, sig1, 0); - - // Step 3: we assume sig1 is valid (it will be verified during step 5) and we verify if 'result' is the prefix of sha256(sig1) - if (!matchBytes32Prefix(sha256(sig1), result, uint(proof[ledgerProofLength+32+8]))) return false; - - // Step 4: commitment match verification, keccak256(delay, nbytes, unonce, sessionKeyHash) == commitment in storage. + copyBytes(_proof, ledgerProofLength, 32, keyhash, 0); + if (!(keccak256(keyhash) == keccak256(abi.encodePacked(sha256(abi.encodePacked(_contextName, _queryId)))))) { + return false; + } + bytes memory sig1 = new bytes(uint(uint8(_proof[ledgerProofLength + (32 + 8 + 1 + 32) + 1])) + 2); + copyBytes(_proof, ledgerProofLength + (32 + 8 + 1 + 32), sig1.length, sig1, 0); + // Random DS Proof Step 3: We assume sig1 is valid (it will be verified during step 5) and we verify if '_result' is the _prefix of sha256(sig1) + if (!matchBytes32Prefix(sha256(sig1), _result, uint(uint8(_proof[ledgerProofLength + 32 + 8])))) { + return false; + } + // Random DS Proof Step 4: Commitment match verification, keccak256(delay, nbytes, unonce, sessionKeyHash) == commitment in storage. // This is to verify that the computed args match with the ones specified in the query. - bytes memory commitmentSlice1 = new bytes(8+1+32); - copyBytes(proof, ledgerProofLength+32, 8+1+32, commitmentSlice1, 0); - + bytes memory commitmentSlice1 = new bytes(8 + 1 + 32); + copyBytes(_proof, ledgerProofLength + 32, 8 + 1 + 32, commitmentSlice1, 0); bytes memory sessionPubkey = new bytes(64); - uint sig2offset = ledgerProofLength+32+(8+1+32)+sig1.length+65; - copyBytes(proof, sig2offset-64, 64, sessionPubkey, 0); - + uint sig2offset = ledgerProofLength + 32 + (8 + 1 + 32) + sig1.length + 65; + copyBytes(_proof, sig2offset - 64, 64, sessionPubkey, 0); bytes32 sessionPubkeyHash = sha256(sessionPubkey); - if (oraclize_randomDS_args[queryId] == keccak256(abi.encodePacked(commitmentSlice1, sessionPubkeyHash))){ //unonce, nbytes and sessionKeyHash match - delete oraclize_randomDS_args[queryId]; + if (oraclize_randomDS_args[_queryId] == keccak256(abi.encodePacked(commitmentSlice1, sessionPubkeyHash))) { //unonce, nbytes and sessionKeyHash match + delete oraclize_randomDS_args[_queryId]; } else return false; - - - // Step 5: validity verification for sig1 (keyhash and args signed with the sessionKey) - bytes memory tosign1 = new bytes(32+8+1+32); - copyBytes(proof, ledgerProofLength, 32+8+1+32, tosign1, 0); - if (!verifySig(sha256(tosign1), sig1, sessionPubkey)) return false; - - // verify if sessionPubkeyHash was verified already, if not.. let's do it! - if (oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash] == false){ - oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash] = oraclize_randomDS_proofVerify__sessionKeyValidity(proof, sig2offset); + // Random DS Proof Step 5: Validity verification for sig1 (keyhash and args signed with the sessionKey) + bytes memory tosign1 = new bytes(32 + 8 + 1 + 32); + copyBytes(_proof, ledgerProofLength, 32 + 8 + 1 + 32, tosign1, 0); + if (!verifySig(sha256(tosign1), sig1, sessionPubkey)) { + return false; + } + // Verify if sessionPubkeyHash was verified already, if not.. let's do it! + if (!oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash]) { + oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash] = oraclize_randomDS_proofVerify__sessionKeyValidity(_proof, sig2offset); } - return oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash]; } - - // the following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license - function copyBytes(bytes from, uint fromOffset, uint length, bytes to, uint toOffset) internal pure returns (bytes) { - uint minLength = length + toOffset; - - // Buffer too small - require(to.length >= minLength); // Should be a better way? - - // NOTE: the offset 32 is added to skip the `size` field of both bytes variables - uint i = 32 + fromOffset; - uint j = 32 + toOffset; - - while (i < (32 + fromOffset + length)) { + /* + The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license + */ + function copyBytes(bytes memory _from, uint _fromOffset, uint _length, bytes memory _to, uint _toOffset) internal pure returns (bytes memory _copiedBytes) { + uint minLength = _length + _toOffset; + require(_to.length >= minLength); // Buffer too small. Should be a better way? + uint i = 32 + _fromOffset; // NOTE: the offset 32 is added to skip the `size` field of both bytes variables + uint j = 32 + _toOffset; + while (i < (32 + _fromOffset + _length)) { assembly { - let tmp := mload(add(from, i)) - mstore(add(to, j), tmp) + let tmp := mload(add(_from, i)) + mstore(add(_to, j), tmp) } i += 32; j += 32; } - - return to; - } - - // the following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license - // Duplicate Solidity's ecrecover, but catching the CALL return value - function safer_ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal returns (bool, address) { - // We do our own memory management here. Solidity uses memory offset - // 0x40 to store the current end of memory. We write past it (as - // writes are memory extensions), but don't update the offset so - // Solidity will reuse it. The memory used here is only needed for - // this context. - - // FIXME: inline assembly can't access return values + return _to; + } + /* + The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license + Duplicate Solidity's ecrecover, but catching the CALL return value + */ + function safer_ecrecover(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal returns (bool _success, address _recoveredAddress) { + /* + We do our own memory management here. Solidity uses memory offset + 0x40 to store the current end of memory. We write past it (as + writes are memory extensions), but don't update the offset so + Solidity will reuse it. The memory used here is only needed for + this context. + FIXME: inline assembly can't access return values + */ bool ret; address addr; - assembly { let size := mload(0x40) - mstore(size, hash) - mstore(add(size, 32), v) - mstore(add(size, 64), r) - mstore(add(size, 96), s) - - // NOTE: we can reuse the request memory because we deal with - // the return code - ret := call(3000, 1, 0, size, 128, size, 32) + mstore(size, _hash) + mstore(add(size, 32), _v) + mstore(add(size, 64), _r) + mstore(add(size, 96), _s) + ret := call(3000, 1, 0, size, 128, size, 32) // NOTE: we can reuse the request memory because we deal with the return code. addr := mload(size) } - return (ret, addr); } - - // the following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license - function ecrecovery(bytes32 hash, bytes sig) internal returns (bool, address) { + /* + The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license + */ + function ecrecovery(bytes32 _hash, bytes memory _sig) internal returns (bool _success, address _recoveredAddress) { bytes32 r; bytes32 s; uint8 v; - - if (sig.length != 65) - return (false, 0); - - // The signature format is a compact form of: - // {bytes32 r}{bytes32 s}{uint8 v} - // Compact means, uint8 is not padded to 32 bytes. + if (_sig.length != 65) { + return (false, address(0)); + } + /* + The signature format is a compact form of: + {bytes32 r}{bytes32 s}{uint8 v} + Compact means, uint8 is not padded to 32 bytes. + */ assembly { - r := mload(add(sig, 32)) - s := mload(add(sig, 64)) - - // Here we are loading the last 32 bytes. We exploit the fact that - // 'mload' will pad with zeroes if we overread. - // There is no 'mload8' to do this, but that would be nicer. - v := byte(0, mload(add(sig, 96))) - - // Alternative solution: - // 'byte' is not working due to the Solidity parser, so lets - // use the second best option, 'and' - // v := and(mload(add(sig, 65)), 255) + r := mload(add(_sig, 32)) + s := mload(add(_sig, 64)) + /* + Here we are loading the last 32 bytes. We exploit the fact that + 'mload' will pad with zeroes if we overread. + There is no 'mload8' to do this, but that would be nicer. + */ + v := byte(0, mload(add(_sig, 96))) + /* + Alternative solution: + 'byte' is not working due to the Solidity parser, so lets + use the second best option, 'and' + v := and(mload(add(_sig, 65)), 255) + */ } - - // albeit non-transactional signatures are not specified by the YP, one would expect it - // to match the YP range of [27, 28] - // - // geth uses [0, 1] and some clients have followed. This might change, see: - // https://github.com/ethereum/go-ethereum/issues/2053 - if (v < 27) - v += 27; - - if (v != 27 && v != 28) - return (false, 0); - - return safer_ecrecover(hash, v, r, s); + /* + albeit non-transactional signatures are not specified by the YP, one would expect it + to match the YP range of [27, 28] + geth uses [0, 1] and some clients have followed. This might change, see: + https://github.com/ethereum/go-ethereum/issues/2053 + */ + if (v < 27) { + v += 27; + } + if (v != 27 && v != 28) { + return (false, address(0)); + } + return safer_ecrecover(_hash, v, r, s); } function safeMemoryCleaner() internal pure { @@ -1230,6 +1330,10 @@ contract usingOraclize { codecopy(fmem, codesize, sub(msize, fmem)) } } - } -// +/* + +END ORACLIZE_API + +*/ + diff --git a/contracts/helpers/PolyToken.sol b/contracts/helpers/PolyToken.sol index ab71ecfda..5230276e3 100644 --- a/contracts/helpers/PolyToken.sol +++ b/contracts/helpers/PolyToken.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../interfaces/IPoly.sol"; @@ -30,7 +30,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @dev Math operations with safety checks that throw on error */ library SafeMath { - function mul(uint256 a, uint256 b) internal pure returns (uint256) { + function mul(uint256 a, uint256 b) internal pure returns(uint256) { if (a == 0) { return 0; } @@ -39,25 +39,26 @@ library SafeMath { return c; } - function div(uint256 a, uint256 b) internal pure returns (uint256) { + 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 c; } - function sub(uint256 a, uint256 b) internal pure returns (uint256) { + function sub(uint256 a, uint256 b) internal pure returns(uint256) { assert(b <= a); return a - b; } - function add(uint256 a, uint256 b) internal pure returns (uint256) { + function add(uint256 a, uint256 b) internal pure returns(uint256) { uint256 c = a + b; assert(c >= a); return c; } } + /** * @title Standard ERC20 token * @@ -73,8 +74,8 @@ contract PolyToken is IPoly { uint8 public constant decimals = 18; uint256 public constant decimalFactor = 10 ** uint256(decimals); uint256 public constant totalSupply = 1000000000 * decimalFactor; - mapping (address => uint256) balances; - mapping (address => mapping (address => uint256)) internal allowed; + mapping(address => uint256) balances; + mapping(address => mapping(address => uint256)) internal allowed; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); @@ -83,7 +84,7 @@ contract PolyToken is IPoly { * @dev Constructor for Poly creation * @dev Assigns the totalSupply to the PolyDistribution contract */ - constructor (address _polyDistributionContractAddress) public { + constructor(address _polyDistributionContractAddress) public { require(_polyDistributionContractAddress != address(0), "Invalid address"); balances[_polyDistributionContractAddress] = totalSupply; emit Transfer(address(0), _polyDistributionContractAddress, totalSupply); @@ -94,7 +95,7 @@ contract PolyToken is IPoly { * @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) { + function balanceOf(address _owner) public view returns(uint256 balance) { return balances[_owner]; } @@ -104,7 +105,7 @@ contract PolyToken is IPoly { * @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) { + function allowance(address _owner, address _spender) public view returns(uint256) { return allowed[_owner][_spender]; } @@ -113,7 +114,7 @@ contract PolyToken is IPoly { * @param _to The address to transfer tokens to * @param _value The amount to be transferred */ - function transfer(address _to, uint256 _value) public returns (bool) { + function transfer(address _to, uint256 _value) public returns(bool) { require(_to != address(0), "Invalid address"); require(_value <= balances[msg.sender], "Insufficient tokens transferable"); @@ -130,7 +131,7 @@ contract PolyToken is IPoly { * @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) { + function transferFrom(address _from, address _to, uint256 _value) public returns(bool) { require(_to != address(0), "Invalid address"); require(_value <= balances[_from], "Insufficient tokens transferable"); require(_value <= allowed[_from][msg.sender], "Insufficient tokens allowable"); @@ -152,7 +153,7 @@ contract PolyToken is IPoly { * @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) { + function approve(address _spender, uint256 _value) public returns(bool) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; @@ -168,7 +169,7 @@ contract PolyToken is IPoly { * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. */ - function increaseApproval(address _spender, uint _addedValue) public returns (bool) { + function increaseApproval(address _spender, uint _addedValue) public returns(bool) { allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; @@ -184,7 +185,7 @@ contract PolyToken is IPoly { * @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) { + function decreaseApproval(address _spender, uint _subtractedValue) public returns(bool) { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; diff --git a/contracts/interfaces/IBoot.sol b/contracts/interfaces/IBoot.sol index db29dc319..ecade0f31 100644 --- a/contracts/interfaces/IBoot.sol +++ b/contracts/interfaces/IBoot.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; 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/interfaces/IFeatureRegistry.sol b/contracts/interfaces/IFeatureRegistry.sol index 574f412a5..563a1a9b8 100644 --- a/contracts/interfaces/IFeatureRegistry.sol +++ b/contracts/interfaces/IFeatureRegistry.sol @@ -1,15 +1,14 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface for managing polymath feature switches */ interface IFeatureRegistry { - /** * @notice Get the status of a feature * @param _nameKey is the key for the feature status mapping * @return bool */ - function getFeatureStatus(string _nameKey) external view returns(bool); + function getFeatureStatus(string calldata _nameKey) external view returns(bool); } diff --git a/contracts/interfaces/IModule.sol b/contracts/interfaces/IModule.sol index bc5140ae2..781ae2a65 100644 --- a/contracts/interfaces/IModule.sol +++ b/contracts/interfaces/IModule.sol @@ -1,19 +1,18 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @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); + function getInitFunction() external pure returns(bytes4); /** * @notice Return the permission flags that are associated with a module */ - function getPermissions() external view returns(bytes32[]); + function getPermissions() external view returns(bytes32[] memory); /** * @notice Used to withdraw the fee by the factory owner diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 9c2ad6bf2..d0a35355d 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface that every module factory contract should implement */ interface IModuleFactory { - event ChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); event ChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); event ChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); @@ -19,12 +18,12 @@ interface IModuleFactory { event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); //Should create an instance of the Module, or throw - function deploy(bytes _data) external returns(address); + function deploy(bytes calldata _data) external returns(address); /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]); + function getTypes() external view returns(uint8[] memory); /** * @notice Get the name of the Module @@ -34,12 +33,12 @@ interface IModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns (string); + function getInstructions() external view returns(string memory); /** * @notice Get the tags related to the module factory */ - function getTags() external view returns (bytes32[]); + function getTags() external view returns(bytes32[] memory); /** * @notice Used to change the setup fee @@ -64,23 +63,23 @@ interface IModuleFactory { * @param _boundType Type of bound * @param _newVersion New version array */ - function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external; + function changeSTVersionBounds(string calldata _boundType, uint8[] calldata _newVersion) external; - /** + /** * @notice Get the setup cost of the module */ - function getSetupCost() external view returns (uint256); + function getSetupCost() external view returns(uint256); /** * @notice Used to get the lower bound * @return Lower bound */ - function getLowerSTVersionBounds() external view returns(uint8[]); + function getLowerSTVersionBounds() external view returns(uint8[] memory); - /** + /** * @notice Used to get the upper bound * @return Upper bound */ - function getUpperSTVersionBounds() external view returns(uint8[]); + function getUpperSTVersionBounds() external view returns(uint8[] memory); } diff --git a/contracts/interfaces/IModuleRegistry.sol b/contracts/interfaces/IModuleRegistry.sol index 0ca6044e4..0d4af763e 100644 --- a/contracts/interfaces/IModuleRegistry.sol +++ b/contracts/interfaces/IModuleRegistry.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface for the Polymath Module Registry contract */ interface IModuleRegistry { - /** * @notice Called by a security token to notify the registry it is using a module * @param _moduleFactory is the address of the relevant module factory @@ -36,7 +35,7 @@ interface IModuleRegistry { * @param _factoryAddress address of the Module Factory * @return address array which has the list of securityToken's uses that module factory */ - function getReputationByFactory(address _factoryAddress) external view returns(address[]); + function getReputationByFactory(address _factoryAddress) external view returns(address[] memory); /** * @notice Returns all the tags related to the a module type which are valid for the given token @@ -45,7 +44,7 @@ interface IModuleRegistry { * @return list of tags * @return corresponding list of module factories */ - function getTagsByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns(bytes32[], address[]); + function getTagsByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns(bytes32[] memory, address[] memory); /** * @notice Returns all the tags related to the a module type which are valid for the given token @@ -53,14 +52,14 @@ interface IModuleRegistry { * @return list of tags * @return corresponding list of module factories */ - function getTagsByType(uint8 _moduleType) external view returns(bytes32[], address[]); + function getTagsByType(uint8 _moduleType) external view returns(bytes32[] memory, address[] memory); /** * @notice Returns the list of addresses of Module Factory of a particular type * @param _moduleType Type of Module * @return address array that contains the list of addresses of module factory contracts. */ - function getModulesByType(uint8 _moduleType) external view returns(address[]); + function getModulesByType(uint8 _moduleType) external view returns(address[] memory); /** * @notice Returns the list of available Module factory addresses of a particular type for a given token. @@ -68,7 +67,7 @@ interface IModuleRegistry { * @param _securityToken is the address of SecurityToken * @return address array that contains the list of available addresses of module factory contracts. */ - function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns (address[]); + function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns(address[] memory); /** * @notice Use to get the latest contract address of the regstries diff --git a/contracts/interfaces/IOracle.sol b/contracts/interfaces/IOracle.sol index 483a22cd0..dc8205a2b 100644 --- a/contracts/interfaces/IOracle.sol +++ b/contracts/interfaces/IOracle.sol @@ -1,7 +1,6 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; interface IOracle { - /** * @notice Returns address of oracle currency (0x0 for ETH) */ diff --git a/contracts/interfaces/IOwnable.sol b/contracts/interfaces/IOwnable.sol index e4f427bd8..9f36abea6 100644 --- a/contracts/interfaces/IOwnable.sol +++ b/contracts/interfaces/IOwnable.sol @@ -1,5 +1,4 @@ -pragma solidity ^0.4.24; - +pragma solidity ^0.5.0; /** * @title Ownable @@ -10,7 +9,7 @@ interface IOwnable { /** * @dev Returns owner */ - function owner() external view returns (address); + function owner() external view returns(address); /** * @dev Allows the current owner to relinquish control of the contract. diff --git a/contracts/interfaces/IPoly.sol b/contracts/interfaces/IPoly.sol index 3d84a468b..0de0cc753 100644 --- a/contracts/interfaces/IPoly.sol +++ b/contracts/interfaces/IPoly.sol @@ -1,19 +1,19 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IPoly { - 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); + 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); } diff --git a/contracts/interfaces/IPolymathRegistry.sol b/contracts/interfaces/IPolymathRegistry.sol index 4601253fa..91a057d54 100644 --- a/contracts/interfaces/IPolymathRegistry.sol +++ b/contracts/interfaces/IPolymathRegistry.sol @@ -1,14 +1,11 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; - interface IPolymathRegistry { - /** * @notice Returns the contract address * @param _nameKey is the key for the contract address mapping * @return address */ - function getAddress(string _nameKey) external view returns(address); + function getAddress(string calldata _nameKey) external view returns(address); } - \ No newline at end of file diff --git a/contracts/interfaces/ISTFactory.sol b/contracts/interfaces/ISTFactory.sol index 7b7d6dd77..e4e2e4dc5 100644 --- a/contracts/interfaces/ISTFactory.sol +++ b/contracts/interfaces/ISTFactory.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface for security token proxy deployment */ interface ISTFactory { - /** * @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. @@ -17,14 +16,14 @@ interface ISTFactory { * @param _polymathRegistry is the address of the Polymath Registry contract */ function deployToken( - string _name, - string _symbol, + string calldata _name, + string calldata _symbol, uint8 _decimals, - string _tokenDetails, + string calldata _tokenDetails, address _issuer, bool _divisible, address _polymathRegistry - ) - external - returns (address); + ) + external + returns(address); } diff --git a/contracts/interfaces/ISTO.sol b/contracts/interfaces/ISTO.sol index ab3d6b3ff..248274e39 100644 --- a/contracts/interfaces/ISTO.sol +++ b/contracts/interfaces/ISTO.sol @@ -1,13 +1,12 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @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); + function getTokensSold() external view returns(uint256); -} \ No newline at end of file +} diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index c2b7ed76f..3228d8740 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -1,20 +1,19 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @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); + 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); @@ -24,10 +23,9 @@ interface ISecurityToken { * @param _from Sender of transfer * @param _to Receiver of transfer * @param _value Value of transfer - * @param _data Data to indicate validation * @return bool */ - function verifyTransfer(address _from, address _to, uint256 _value, bytes _data) external returns (bool); + function verifyTransfer(address _from, address _to, uint256 _value, bytes calldata _data) external returns(bool success); /** * @notice Mints new tokens and assigns them to the target _investor. @@ -36,7 +34,7 @@ interface ISecurityToken { * @param _value is the amount of tokens that will be minted to the investor * @return success */ - function mint(address _investor, uint256 _value) external returns (bool success); + function mint(address _investor, uint256 _value) external returns(bool success); /** * @notice Mints new tokens and assigns them to the target _investor. @@ -45,7 +43,7 @@ interface ISecurityToken { * @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); + function mintWithData(address _investor, uint256 _value, bytes calldata _data) external returns(bool success); /** * @notice Used to burn the securityToken on behalf of someone else @@ -53,14 +51,14 @@ interface ISecurityToken { * @param _value No. of tokens to be burned * @param _data Data to indicate validation */ - function burnFromWithData(address _from, uint256 _value, bytes _data) external; + function burnFromWithData(address _from, uint256 _value, bytes calldata _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; + function burnWithData(uint256 _value, bytes calldata _data) external; event Minted(address indexed _to, uint256 _value); event Burnt(address indexed _burner, uint256 _value); @@ -74,7 +72,7 @@ interface ISecurityToken { * @param _perm the permissions * @return success */ - function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns (bool); + function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns(bool); /** * @notice Returns module list for a module type @@ -86,52 +84,52 @@ interface ISecurityToken { * @return uint8 Array of module types * @return bytes32 Module label */ - function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[], bytes32); + function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[] memory, bytes32); /** * @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[]); + function getModulesByName(bytes32 _name) external view returns(address[] memory); /** * @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[]); + function getModulesByType(uint8 _type) external view returns(address[] memory); /** * @notice Queries totalSupply at a specified checkpoint * @param _checkpointId Checkpoint ID to query as of */ - function totalSupplyAt(uint256 _checkpointId) external view returns (uint256); + 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); + 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); + function createCheckpoint() external returns(uint256); /** * @notice Gets list of times that checkpoints were created * @return List of checkpoint times */ - function getCheckpointTimes() external view returns(uint256[]); + function getCheckpointTimes() external view returns(uint256[] memory); /** * @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[]); + function getInvestors() external view returns(address[] memory); /** * @notice returns an array of investors at a given checkpoint @@ -139,7 +137,7 @@ interface ISecurityToken { * @param _checkpointId Checkpoint id at which investor list is to be populated * @return list of investors */ - function getInvestorsAt(uint256 _checkpointId) external view returns(address[]); + function getInvestorsAt(uint256 _checkpointId) external view returns(address[] memory); /** * @notice generates subset of investors @@ -148,13 +146,13 @@ interface ISecurityToken { * @param _end Position of investor to stop iteration at * @return list of investors */ - function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]); - + function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[] memory); + /** * @notice Gets current checkpoint ID * @return Id */ - function currentCheckpointId() external view returns (uint256); + function currentCheckpointId() external view returns(uint256); /** * @notice Allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. @@ -176,7 +174,7 @@ interface ISecurityToken { * @notice Changes the tokenDetails * @param _newTokenDetails New token details */ - function updateTokenDetails(string _newTokenDetails) external; + function updateTokenDetails(string calldata _newTokenDetails) external; /** * @notice Allows the owner to change token granularity @@ -206,7 +204,7 @@ interface ISecurityToken { * @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); + function mintMulti(address[] calldata _investors, uint256[] calldata _values) external returns(bool success); /** * @notice Attachs a module to the SecurityToken @@ -220,7 +218,7 @@ interface ISecurityToken { */ function addModuleWithLabel( address _moduleFactory, - bytes _data, + bytes calldata _data, uint256 _maxCost, uint256 _budget, bytes32 _label @@ -238,12 +236,7 @@ interface ISecurityToken { * @param _maxCost max amount of POLY willing to pay to module. (WIP) * @param _budget max amount of ongoing POLY willing to assign to the module. */ - function addModule( - address _moduleFactory, - bytes _data, - uint256 _maxCost, - uint256 _budget - ) external; + function addModule(address _moduleFactory, bytes calldata _data, uint256 _maxCost, uint256 _budget) external; /** * @notice Archives a module attached to the SecurityToken @@ -277,7 +270,7 @@ interface ISecurityToken { * @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; + function forceTransfer(address _from, address _to, uint256 _value, bytes calldata _data, bytes calldata _log) external; /** * @notice Used by a controller to execute a foced burn @@ -286,34 +279,34 @@ interface ISecurityToken { * @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; + function forceBurn(address _from, uint256 _value, bytes calldata _data, bytes calldata _log) external; /** * @notice Used by the issuer to permanently disable controller functionality * @dev enabled via feature switch "disableControllerAllowed" */ - function disableController() external; + function disableController() external; - /** + /** * @notice Used to get the version of the securityToken */ - function getVersion() external view returns(uint8[]); + function getVersion() external view returns(uint8[] memory); - /** + /** * @notice Gets the investor count */ - function getInvestorCount() external view returns(uint256); + 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); + function transferWithData(address _to, uint256 _value, bytes calldata _data) external returns(bool success); - /** + /** * @notice Overloaded version of the transferFrom function * @param _from sender of transfer * @param _to receiver of transfer @@ -321,11 +314,11 @@ interface ISecurityToken { * @param _data data to indicate validation * @return bool success */ - function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) external returns(bool); + function transferFromWithData(address _from, address _to, uint256 _value, bytes calldata _data) external returns(bool); - /** + /** * @notice Provides the granularity of the token * @return uint256 */ - function granularity() external view returns(uint256); + function granularity() external view returns(uint256); } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 1e1c82b49..18e1e6951 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -1,18 +1,17 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface for the Polymath Security Token Registry contract */ 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 */ - function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external; + function generateSecurityToken(string calldata _name, string calldata _ticker, string calldata _tokenDetails, bool _divisible) external; /** * @notice Adds a new custom Security Token and saves it to the registry. (Token should follow the ISecurityToken interface) @@ -24,14 +23,14 @@ interface ISecurityTokenRegistry { * @param _deployedAt Timestamp at which security token comes deployed on the ethereum blockchain */ function modifySecurityToken( - string _name, - string _ticker, + string calldata _name, + string calldata _ticker, address _owner, address _securityToken, - string _tokenDetails, + string calldata _tokenDetails, uint256 _deployedAt - ) - external; + ) + external; /** * @notice Registers the token ticker for its particular owner @@ -41,7 +40,7 @@ interface ISecurityTokenRegistry { * @param _ticker Token ticker * @param _tokenName Name of the token */ - function registerTicker(address _owner, string _ticker, string _tokenName) external; + function registerTicker(address _owner, string calldata _ticker, string calldata _tokenName) external; /** * @notice Changes the protocol version and the SecurityToken contract @@ -59,7 +58,7 @@ interface ISecurityTokenRegistry { * @param _securityToken Address of the Scurity token * @return bool */ - function isSecurityToken(address _securityToken) external view returns (bool); + function isSecurityToken(address _securityToken) external view returns(bool); /** * @dev Allows the current owner to transfer control of the contract to a newOwner. @@ -72,9 +71,9 @@ interface ISecurityTokenRegistry { * @param _ticker Symbol of the Scurity token * @return address */ - function getSecurityTokenAddress(string _ticker) external view returns (address); + function getSecurityTokenAddress(string calldata _ticker) external view returns(address); - /** + /** * @notice Get security token data by its address * @param _securityToken Address of the Scurity token. * @return string Symbol of the Security Token. @@ -82,7 +81,7 @@ interface ISecurityTokenRegistry { * @return string Details of the Token. * @return uint256 Timestamp at which Security Token get launched on Polymath platform. */ - function getSecurityTokenData(address _securityToken) external view returns (string, address, string, uint256); + function getSecurityTokenData(address _securityToken) external view returns(string memory, address, string memory, uint256); /** * @notice Get the current STFactory Address @@ -92,26 +91,26 @@ interface ISecurityTokenRegistry { /** * @notice Get Protocol version */ - function getProtocolVersion() external view returns(uint8[]); + function getProtocolVersion() external view returns(uint8[] memory); /** * @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[]); + function getTickersByOwner(address _owner) external view returns(bytes32[] memory); /** * @notice Returns the list of tokens owned by the selected address * @param _owner is the address which owns the list of tickers * @dev Intention is that this is called off-chain so block gas limit is not relevant */ - function getTokensByOwner(address _owner) external view returns(address[]); + function getTokensByOwner(address _owner) external view returns(address[] memory); /** * @notice Returns the list of all tokens * @dev Intention is that this is called off-chain so block gas limit is not relevant */ - function getTokens() external view returns(address[]); + function getTokens() external view returns(address[] memory); /** * @notice Returns the owner and timestamp for a given ticker @@ -122,7 +121,7 @@ interface ISecurityTokenRegistry { * @return string * @return bool */ - function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool); + function getTickerDetails(string calldata _ticker) external view returns(address, uint256, uint256, string memory, bool); /** * @notice Modifies the ticker details. Only polymath account has the ability @@ -136,26 +135,26 @@ interface ISecurityTokenRegistry { */ function modifyTicker( address _owner, - string _ticker, - string _tokenName, + string calldata _ticker, + string calldata _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status - ) - external; + ) + external; - /** + /** * @notice Removes the ticker details and associated ownership & security token mapping * @param _ticker Token ticker */ - function removeTicker(string _ticker) external; + function removeTicker(string calldata _ticker) external; /** * @notice Transfers the ownership of the ticker * @dev _newOwner Address whom ownership to transfer * @dev _ticker Ticker */ - function transferTickerOwnership(address _newOwner, string _ticker) external; + function transferTickerOwnership(address _newOwner, string calldata _ticker) external; /** * @notice Changes the expiry time for the token ticker @@ -167,13 +166,13 @@ interface ISecurityTokenRegistry { * @notice Sets the ticker registration fee in POLY tokens * @param _tickerRegFee Registration fee in POLY tokens (base 18 decimals) */ - function changeTickerRegistrationFee(uint256 _tickerRegFee) external; + function changeTickerRegistrationFee(uint256 _tickerRegFee) external; - /** + /** * @notice Sets the ticker registration fee in POLY tokens * @param _stLaunchFee Registration fee in POLY tokens (base 18 decimals) */ - function changeSecurityLaunchFee(uint256 _stLaunchFee) external; + function changeSecurityLaunchFee(uint256 _stLaunchFee) external; /** * @notice Gets the security token launch fee diff --git a/contracts/interfaces/ITransferManager.sol b/contracts/interfaces/ITransferManager.sol index b5819c63d..b248a98b3 100644 --- a/contracts/interfaces/ITransferManager.sol +++ b/contracts/interfaces/ITransferManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./TransferManagerEnums.sol"; @@ -6,10 +6,11 @@ import "./TransferManagerEnums.sol"; * @title Interface to be implemented by all Transfer Manager modules */ interface ITransferManager { - /** * @notice Determines if the transfer between these two accounts can happen */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data, bool _isTransfer) external returns(TransferManagerEnums.Result); + function verifyTransfer(address _from, address _to, uint256 _amount, bytes calldata _data, bool _isTransfer) external returns( + TransferManagerEnums.Result + ); -} \ No newline at end of file +} diff --git a/contracts/interfaces/IUSDTieredSTOProxy.sol b/contracts/interfaces/IUSDTieredSTOProxy.sol index 480cee059..bcbf2b2d9 100644 --- a/contracts/interfaces/IUSDTieredSTOProxy.sol +++ b/contracts/interfaces/IUSDTieredSTOProxy.sol @@ -1,23 +1,22 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface for security token proxy deployment */ interface IUSDTieredSTOProxy { - - /** + /** * @notice Deploys the STO. * @param _securityToken Contract address of the securityToken * @param _factoryAddress Contract address of the factory * @return address Address of the deployed STO */ - function deploySTO(address _securityToken, address _factoryAddress) external returns (address); - - /** + function deploySTO(address _securityToken, address _factoryAddress) external returns(address); + + /** * @notice Used to get the init function signature * @param _contractAddress Address of the STO contract * @return bytes4 */ - function getInitFunction(address _contractAddress) external returns (bytes4); + function getInitFunction(address _contractAddress) external returns(bytes4); -} \ No newline at end of file +} diff --git a/contracts/interfaces/TransferManagerEnums.sol b/contracts/interfaces/TransferManagerEnums.sol index 2b7e85853..c097dddc7 100644 --- a/contracts/interfaces/TransferManagerEnums.sol +++ b/contracts/interfaces/TransferManagerEnums.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Container contract for transfer manager enums */ contract TransferManagerEnums { - //If verifyTransfer returns: // FORCE_VALID, the transaction will always be valid, regardless of other TM results // INVALID, then the transfer should not be allowed regardless of other TM results @@ -12,4 +11,4 @@ contract TransferManagerEnums { // NA, then the result from this TM is ignored enum Result {INVALID, NA, VALID, FORCE_VALID} -} \ No newline at end of file +} diff --git a/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol index 29de4d7cd..fdfd3df2e 100644 --- a/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol +++ b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; // ---------------------------------------------------------------------------- // BokkyPooBah's DateTime Library v1.00 @@ -29,7 +29,6 @@ pragma solidity ^0.4.24; // ---------------------------------------------------------------------------- library BokkyPooBahsDateTimeLibrary { - uint constant SECONDS_PER_DAY = 24 * 60 * 60; uint constant SECONDS_PER_HOUR = 60 * 60; uint constant SECONDS_PER_MINUTE = 60; @@ -56,18 +55,13 @@ library BokkyPooBahsDateTimeLibrary { // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 // - offset // ------------------------------------------------------------------------ - function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) { + 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; + 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); } @@ -89,7 +83,7 @@ library BokkyPooBahsDateTimeLibrary { // month = month + 2 - 12 * L // year = 100 * (N - 49) + year + L // ------------------------------------------------------------------------ - function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) { + function _daysToDate(uint _days) internal pure returns(uint year, uint month, uint day) { int __days = int(_days); int L = __days + 68569 + OFFSET19700101; @@ -108,16 +102,26 @@ library BokkyPooBahsDateTimeLibrary { day = uint(_day); } - function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) { + 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) { + 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) { + 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) { + 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; @@ -126,7 +130,7 @@ library BokkyPooBahsDateTimeLibrary { second = secs % SECONDS_PER_MINUTE; } - function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) { + 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) { @@ -134,37 +138,37 @@ library BokkyPooBahsDateTimeLibrary { } } } - function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) { + 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) { + 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) { + 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) { + function isWeekDay(uint timestamp) internal pure returns(bool weekDay) { weekDay = getDayOfWeek(timestamp) <= DOW_FRI; } - function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) { + function isWeekEnd(uint timestamp) internal pure returns(bool weekEnd) { weekEnd = getDayOfWeek(timestamp) >= DOW_SAT; } - function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) { + 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) { + 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) { @@ -174,39 +178,39 @@ library BokkyPooBahsDateTimeLibrary { } } // 1 = Monday, 7 = Sunday - function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + function addYears(uint timestamp, uint _years) internal pure returns(uint newTimestamp) { uint year; uint month; uint day; @@ -219,7 +223,8 @@ library BokkyPooBahsDateTimeLibrary { 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) { + + function addMonths(uint timestamp, uint _months) internal pure returns(uint newTimestamp) { uint year; uint month; uint day; @@ -234,24 +239,28 @@ library BokkyPooBahsDateTimeLibrary { 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) { + + 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) { + + 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) { + + 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) { + + 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) { + function subYears(uint timestamp, uint _years) internal pure returns(uint newTimestamp) { uint year; uint month; uint day; @@ -264,7 +273,8 @@ library BokkyPooBahsDateTimeLibrary { 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) { + + function subMonths(uint timestamp, uint _months) internal pure returns(uint newTimestamp) { uint year; uint month; uint day; @@ -279,24 +289,28 @@ library BokkyPooBahsDateTimeLibrary { 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) { + + 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) { + + 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) { + + 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) { + + 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) { + function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns(uint _years) { require(fromTimestamp <= toTimestamp); uint fromYear; uint fromMonth; @@ -308,7 +322,8 @@ library BokkyPooBahsDateTimeLibrary { (toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY); _years = toYear - fromYear; } - function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) { + + function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns(uint _months) { require(fromTimestamp <= toTimestamp); uint fromYear; uint fromMonth; @@ -320,19 +335,23 @@ library BokkyPooBahsDateTimeLibrary { (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) { + + 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) { + + 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) { + + 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) { + + function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns(uint _seconds) { require(fromTimestamp <= toTimestamp); _seconds = toTimestamp - fromTimestamp; } diff --git a/contracts/libraries/DecimalMath.sol b/contracts/libraries/DecimalMath.sol index 242daffab..ab942bad2 100644 --- a/contracts/libraries/DecimalMath.sol +++ b/contracts/libraries/DecimalMath.sol @@ -1,16 +1,15 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; library DecimalMath { - using SafeMath for uint256; - /** + /** * @notice This function multiplies two decimals represented as (decimal * 10**DECIMALS) * @return uint256 Result of multiplication represented as (decimal * 10**DECIMALS) */ - function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { + function mul(uint256 x, uint256 y) internal pure returns(uint256 z) { z = SafeMath.add(SafeMath.mul(x, y), (10 ** 18) / 2) / (10 ** 18); } @@ -18,8 +17,8 @@ library DecimalMath { * @notice This function divides two decimals represented as (decimal * 10**DECIMALS) * @return uint256 Result of division represented as (decimal * 10**DECIMALS) */ - function div(uint256 x, uint256 y) internal pure returns (uint256 z) { + function div(uint256 x, uint256 y) internal pure returns(uint256 z) { z = SafeMath.add(SafeMath.mul(x, (10 ** 18)), y / 2) / y; } -} \ No newline at end of file +} diff --git a/contracts/libraries/Encoder.sol b/contracts/libraries/Encoder.sol index 27d9a4ddf..b3cf9124d 100644 --- a/contracts/libraries/Encoder.sol +++ b/contracts/libraries/Encoder.sol @@ -1,28 +1,27 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; library Encoder { - - function getKey(string _key) internal pure returns (bytes32) { + function getKey(string memory _key) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key))); } - function getKey(string _key1, address _key2) internal pure returns (bytes32) { + function getKey(string memory _key1, address _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function getKey(string _key1, string _key2) internal pure returns (bytes32) { + function getKey(string memory _key1, string memory _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function getKey(string _key1, uint256 _key2) internal pure returns (bytes32) { + function getKey(string memory _key1, uint256 _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function getKey(string _key1, bytes32 _key2) internal pure returns (bytes32) { + function getKey(string memory _key1, bytes32 _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function getKey(string _key1, bool _key2) internal pure returns (bytes32) { + function getKey(string memory _key1, bool _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } diff --git a/contracts/libraries/KindMath.sol b/contracts/libraries/KindMath.sol index 850926088..00810abb1 100644 --- a/contracts/libraries/KindMath.sol +++ b/contracts/libraries/KindMath.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; // Copied from OpenZeppelin and modified to be friendlier @@ -7,11 +7,10 @@ pragma solidity ^0.4.24; * @dev Math operations with safety checks that throw on error */ library KindMath { - /** * @dev Multiplies two numbers, throws on overflow. */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { + function mul(uint256 a, uint256 b) internal pure returns(uint256 c) { // Gas optimization: this is cheaper than requireing 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 @@ -27,7 +26,7 @@ library KindMath { /** * @dev Integer division of two numbers, truncating the quotient. */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { + function div(uint256 a, uint256 b) internal pure returns(uint256) { // require(b > 0); // Solidity automatically throws when dividing by 0 // uint256 c = a / b; // require(a == b * c + a % b); // There is no case in which this doesn't hold @@ -37,7 +36,7 @@ library KindMath { /** * @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) { + function sub(uint256 a, uint256 b) internal pure returns(uint256) { require(b <= a, "sub overflow"); return a - b; } @@ -45,7 +44,7 @@ library KindMath { /** * @dev Adds two numbers, throws on overflow. */ - function add(uint256 a, uint256 b) internal pure returns (uint256 c) { + function add(uint256 a, uint256 b) internal pure returns(uint256 c) { c = a + b; require(c >= a, "add overflow"); return c; diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 8c823ae29..8585a3dba 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -1,10 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/PermissionManager/IPermissionManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../interfaces/IPoly.sol"; library TokenLib { - using SafeMath for uint256; // Struct for module data @@ -27,7 +27,7 @@ library TokenLib { struct InvestorDataStorage { // List of investors who have ever held a non-zero token balance - mapping (address => bool) investorListed; + mapping(address => bool) investorListed; // List of token holders address[] investors; // Total number of non-zero token holders @@ -38,6 +38,10 @@ library TokenLib { event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp); // Emit when Module is unarchived from the SecurityToken event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp); + // Emit when Module get removed from the securityToken + event ModuleRemoved(uint8[] _types, address _module, uint256 _timestamp); + // Emit when the budget allocated to a module is changed + event ModuleBudgetChanged(uint8[] _moduleTypes, address _module, uint256 _oldBudget, uint256 _budget); /** * @notice Archives a module attached to the SecurityToken @@ -64,6 +68,95 @@ library TokenLib { _moduleData.isArchived = false; } + /** + * @notice Removes a module attached to the SecurityToken + * @param _module address of module to unarchive + */ + function removeModule( + address _module, + mapping(uint8 => address[]) storage _modules, + mapping(address => ModuleData) storage _modulesToData, + mapping(bytes32 => address[]) storage _names + ) + public + { + 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; + for (uint256 i = 0; i < moduleTypes.length; i++) { + _removeModuleWithIndex(moduleTypes[i], _modulesToData[_module].moduleIndexes[i], _modules, _modulesToData); + /* modulesToData[_module].moduleType[moduleTypes[i]] = false; */ + } + // Remove from module names list + uint256 index = _modulesToData[_module].nameIndex; + bytes32 name = _modulesToData[_module].name; + uint256 length = _names[name].length; + _names[name][index] = _names[name][length - 1]; + _names[name].length = length - 1; + if ((length - 1) != index) { + _modulesToData[_names[name][index]].nameIndex = index; + } + // Remove from modulesToData + delete _modulesToData[_module]; + } + + /** + * @notice Internal - Removes a module attached to the SecurityToken by index + */ + function _removeModuleWithIndex( + uint8 _type, + uint256 _index, + mapping(uint8 => address[]) storage _modules, + mapping(address => ModuleData) storage _modulesToData + ) + internal + { + uint256 length = _modules[_type].length; + _modules[_type][_index] = _modules[_type][length - 1]; + _modules[_type].length = length - 1; + + if ((length - 1) != _index) { + //Need to find index of _type in moduleTypes of module we are moving + uint8[] memory newTypes = _modulesToData[_modules[_type][_index]].moduleTypes; + for (uint256 i = 0; i < newTypes.length; i++) { + if (newTypes[i] == _type) { + _modulesToData[_modules[_type][_index]].moduleIndexes[i] = _index; + } + } + } + } + + /** + * @notice allows owner to increase/decrease POLY approval of one of the modules + * @param _module module address + * @param _change change in allowance + * @param _increase true if budget has to be increased, false if decrease + */ + function changeModuleBudget( + address _module, + uint256 _change, + bool _increase, + address _polyToken, + mapping(address => ModuleData) storage _modulesToData + ) + public + { + require(_modulesToData[_module].module != address(0), "Module missing"); + uint256 currentAllowance = IPoly(_polyToken).allowance(address(this), _module); + uint256 newAllowance; + if (_increase) { + require(IPoly(_polyToken).increaseApproval(_module, _change), "IncreaseApproval fail"); + newAllowance = currentAllowance.add(_change); + } else { + require(IPoly(_polyToken).decreaseApproval(_module, _change), "Insufficient allowance"); + newAllowance = currentAllowance.sub(_change); + } + emit ModuleBudgetChanged(_modulesToData[_module].moduleTypes, _module, currentAllowance, newAllowance); + } + /** * @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 @@ -144,12 +237,7 @@ library TokenLib { return; } //New checkpoint, so record balance - _checkpoints.push( - TokenLib.Checkpoint({ - checkpointId: _currentCheckpointId, - value: _newValue - }) - ); + _checkpoints.push(TokenLib.Checkpoint({checkpointId: _currentCheckpointId, value: _newValue})); } /** @@ -168,7 +256,9 @@ library TokenLib { uint256 _value, uint256 _balanceTo, uint256 _balanceFrom - ) public { + ) + public + { if ((_value == 0) || (_from == _to)) { return; } diff --git a/contracts/libraries/Util.sol b/contracts/libraries/Util.sol index 5d4cce83e..b502ca305 100644 --- a/contracts/libraries/Util.sol +++ b/contracts/libraries/Util.sol @@ -1,20 +1,19 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Utility contract for reusable code */ library Util { - - /** + /** * @notice Changes a string to upper case * @param _base String to change */ - function upper(string _base) internal pure returns (string) { + function upper(string memory _base) internal pure returns(string memory) { bytes memory _baseBytes = bytes(_base); for (uint i = 0; i < _baseBytes.length; i++) { bytes1 b1 = _baseBytes[i]; if (b1 >= 0x61 && b1 <= 0x7A) { - b1 = bytes1(uint8(b1)-32); + b1 = bytes1(uint8(b1) - 32); } _baseBytes[i] = b1; } @@ -26,7 +25,7 @@ library Util { * @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. - function stringToBytes32(string memory _source) internal pure returns (bytes32) { + function stringToBytes32(string memory _source) internal pure returns(bytes32) { return bytesToBytes32(bytes(_source), 0); } @@ -36,7 +35,7 @@ library Util { * @param _offset Offset from which to begin conversion */ /// Notice - Maximum length for _source will be 32 chars otherwise returned bytes32 value will have lossy value. - function bytesToBytes32(bytes _b, uint _offset) internal pure returns (bytes32) { + function bytesToBytes32(bytes memory _b, uint _offset) internal pure returns(bytes32) { bytes32 result; for (uint i = 0; i < _b.length; i++) { @@ -49,10 +48,11 @@ library Util { * @notice Changes the bytes32 into string * @param _source that need to convert into string */ - function bytes32ToString(bytes32 _source) internal pure returns (string result) { + function bytes32ToString(bytes32 _source) internal pure returns(string memory) { bytes memory bytesString = new bytes(32); uint charCount = 0; - for (uint j = 0; j < 32; j++) { + uint j = 0; + for (j = 0; j < 32; j++) { byte char = byte(bytes32(uint(_source) * 2 ** (8 * j))); if (char != 0) { bytesString[charCount] = char; @@ -71,12 +71,11 @@ library Util { * @param _data Passed data * @return bytes4 sig */ - function getSig(bytes _data) internal pure returns (bytes4 sig) { + function getSig(bytes memory _data) internal pure returns(bytes4 sig) { uint len = _data.length < 4 ? _data.length : 4; - for (uint i = 0; i < len; i++) { - sig = bytes4(uint(sig) + uint(_data[i]) * (2 ** (8 * (len - 1 - i)))); + for (uint256 i = 0; i < len; i++) { + sig |= bytes4(_data[i] & 0xFF) >> (i * 8); } + return sig; } - - } diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 71376aa45..645e183b4 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -1,48 +1,39 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Helper library use to compare or validate the semantic versions */ library VersionUtils { - /** * @notice This function is used to validate the version submitted * @param _current Array holds the present version of ST * @param _new Array holds the latest version of the ST * @return bool */ - function isValidVersion(uint8[] _current, uint8[] _new) internal pure returns(bool) { + function isValidVersion(uint8[] memory _current, uint8[] memory _new) internal pure returns(bool) { bool[] memory _temp = new bool[](_current.length); uint8 counter = 0; - for (uint8 i = 0; i < _current.length; i++) { - if (_current[i] < _new[i]) - _temp[i] = true; - else - _temp[i] = false; + uint8 i = 0; + for (i = 0; i < _current.length; i++) { + if (_current[i] < _new[i]) _temp[i] = true; + else _temp[i] = false; } for (i = 0; i < _current.length; i++) { if (i == 0) { - if (_current[i] <= _new[i]) - if(_temp[0]) { - counter = counter + 3; - break; - } else - counter++; - else - return false; + if (_current[i] <= _new[i]) if (_temp[0]) { + counter = counter + 3; + break; + } else counter++; + else return false; } else { - if (_temp[i-1]) - counter++; - else if (_current[i] <= _new[i]) - counter++; - else - return false; + if (_temp[i - 1]) counter++; + else if (_current[i] <= _new[i]) counter++; + else return false; } } - if (counter == _current.length) - return true; + if (counter == _current.length) return true; } /** @@ -51,29 +42,22 @@ library VersionUtils { * @param _version2 Array holds the latest version of the ST * @return bool */ - function compareLowerBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { + function compareLowerBound(uint8[] memory _version1, uint8[] memory _version2) internal pure returns(bool) { require(_version1.length == _version2.length, "Input length mismatch"); uint counter = 0; for (uint8 j = 0; j < _version1.length; j++) { - if (_version1[j] == 0) - counter ++; + if (_version1[j] == 0) counter++; } if (counter != _version1.length) { counter = 0; for (uint8 i = 0; i < _version1.length; i++) { - if (_version2[i] > _version1[i]) - return true; - else if (_version2[i] < _version1[i]) - return false; - else - counter++; + if (_version2[i] > _version1[i]) return true; + else if (_version2[i] < _version1[i]) return false; + else counter++; } - if (counter == _version1.length - 1) - return true; - else - return false; - } else - return true; + if (counter == _version1.length - 1) return true; + else return false; + } else return true; } /** @@ -82,32 +66,24 @@ library VersionUtils { * @param _version2 Array holds the latest version of the ST * @return bool */ - function compareUpperBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { + function compareUpperBound(uint8[] memory _version1, uint8[] memory _version2) internal pure returns(bool) { require(_version1.length == _version2.length, "Input length mismatch"); uint counter = 0; for (uint8 j = 0; j < _version1.length; j++) { - if (_version1[j] == 0) - counter ++; + if (_version1[j] == 0) counter++; } if (counter != _version1.length) { counter = 0; for (uint8 i = 0; i < _version1.length; i++) { - if (_version1[i] > _version2[i]) - return true; - else if (_version1[i] < _version2[i]) - return false; - else - counter++; + if (_version1[i] > _version2[i]) return true; + else if (_version1[i] < _version2[i]) return false; + else counter++; } - if (counter == _version1.length - 1) - return true; - else - return false; - } else - return true; + if (counter == _version1.length - 1) return true; + else return false; + } else return true; } - /** * @notice Used to pack the uint8[] array data into uint24 value * @param _major Major version @@ -122,7 +98,7 @@ library VersionUtils { * @notice Used to convert packed data into uint8 array * @param _packedVersion Packed data */ - function unpack(uint24 _packedVersion) internal pure returns (uint8[]) { + function unpack(uint24 _packedVersion) internal pure returns(uint8[] memory) { uint8[] memory _unpackVersion = new uint8[](3); _unpackVersion[0] = uint8(_packedVersion >> 16); _unpackVersion[1] = uint8(_packedVersion >> 8); @@ -130,5 +106,4 @@ library VersionUtils { return _unpackVersion; } - } diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index a5f365050..720c480f7 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./MockRedemptionManager.sol"; import "../modules/Experimental/Burn/TrackedRedemptionFactory.sol"; @@ -8,23 +8,33 @@ import "../modules/Experimental/Burn/TrackedRedemptionFactory.sol"; */ contract MockBurnFactory is TrackedRedemptionFactory { - /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - TrackedRedemptionFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost + ) + public + TrackedRedemptionFactory(_setupCost, _usageCost, _subscriptionCost) { + } /** * @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 calldata /*_data*/ + ) + external + returns(address) + { address polyToken = _takeFee(); //Check valid bytes - can only call module init function MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, polyToken); diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 73f5aaa27..558323584 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/STO/DummySTOFactory.sol"; @@ -7,7 +7,6 @@ import "../modules/STO/DummySTOFactory.sol"; */ contract MockFactory is DummySTOFactory { - bool public switchTypes = false; /** @@ -17,16 +16,21 @@ contract MockFactory is DummySTOFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) { - } /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { if (!switchTypes) { uint8[] memory types = new uint8[](0); return types; @@ -36,7 +40,7 @@ contract MockFactory is DummySTOFactory { res[1] = 1; return res; } - + } function changeTypes() external onlyOwner { diff --git a/contracts/mocks/MockModuleRegistry.sol b/contracts/mocks/MockModuleRegistry.sol index 5711108c1..8dccc7bf6 100644 --- a/contracts/mocks/MockModuleRegistry.sol +++ b/contracts/mocks/MockModuleRegistry.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleRegistry.sol"; @@ -6,14 +6,12 @@ import "../ModuleRegistry.sol"; * @title Registry contract for issuers to register their security tokens */ contract MockModuleRegistry is ModuleRegistry { - /// @notice It is dummy functionality /// Alert! Alert! Do not use it for the mainnet release - function addMoreReputation(address _moduleFactory, address[] _tokens) public onlyOwner { + function addMoreReputation(address _moduleFactory, address[] memory _tokens) public onlyOwner { for (uint8 i = 0; i < _tokens.length; i++) { pushArray(Encoder.getKey("reputation", _moduleFactory), _tokens[i]); } } - } diff --git a/contracts/mocks/MockOracle.sol b/contracts/mocks/MockOracle.sol index d7cf14a2a..8208f8024 100644 --- a/contracts/mocks/MockOracle.sol +++ b/contracts/mocks/MockOracle.sol @@ -1,9 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../interfaces/IOracle.sol"; contract MockOracle is IOracle { - address public currency; bytes32 public currencySymbol; bytes32 public denominatedCurrency; diff --git a/contracts/mocks/MockPolyOracle.sol b/contracts/mocks/MockPolyOracle.sol index 681bb2681..15041a42d 100644 --- a/contracts/mocks/MockPolyOracle.sol +++ b/contracts/mocks/MockPolyOracle.sol @@ -1,11 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../oracles/PolyOracle.sol"; contract MockPolyOracle is PolyOracle { - - constructor() payable public { + constructor() public payable { OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475); } -} \ No newline at end of file +} diff --git a/contracts/mocks/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol index 8f7abfb80..f5d117497 100644 --- a/contracts/mocks/MockRedemptionManager.sol +++ b/contracts/mocks/MockRedemptionManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/Experimental/Burn/TrackedRedemption.sol"; @@ -6,8 +6,7 @@ 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; + mapping(address => uint256) tokenToRedeem; event RedeemedTokenByOwner(address _investor, address _byWhoom, uint256 _value, uint256 _timestamp); @@ -15,9 +14,8 @@ contract MockRedemptionManager is TrackedRedemption { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - TrackedRedemption(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public TrackedRedemption(_securityToken, _polyToken) { + } /** diff --git a/contracts/mocks/MockWrongTypeFactory.sol b/contracts/mocks/MockWrongTypeFactory.sol index 9da441072..a5d2b74ec 100644 --- a/contracts/mocks/MockWrongTypeFactory.sol +++ b/contracts/mocks/MockWrongTypeFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./MockBurnFactory.sol"; import "../modules/ModuleFactory.sol"; @@ -9,22 +9,27 @@ import "../libraries/Util.sol"; */ contract MockWrongTypeFactory is MockBurnFactory { - /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - MockBurnFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost + ) + public + MockBurnFactory(_setupCost, _usageCost, _subscriptionCost) { + } /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory types = new uint8[](1); types[0] = 4; return types; diff --git a/contracts/mocks/PolyTokenFaucet.sol b/contracts/mocks/PolyTokenFaucet.sol index 76f1a5596..c903223f6 100644 --- a/contracts/mocks/PolyTokenFaucet.sol +++ b/contracts/mocks/PolyTokenFaucet.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -8,7 +8,6 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; */ contract PolyTokenFaucet { - using SafeMath for uint256; uint256 totalSupply_; string public name = "Polymath Network"; @@ -23,14 +22,14 @@ contract PolyTokenFaucet { constructor() public { decimals = 18; - totalSupply_ = 1000000 * uint256(10)**decimals; + totalSupply_ = 1000000 * uint256(10) ** decimals; balances[msg.sender] = totalSupply_; emit Transfer(address(0), msg.sender, totalSupply_); } /* Token faucet - Not part of the ERC20 standard */ - function getTokens(uint256 _amount, address _recipient) public returns (bool) { - require(_amount <= 1000000 * uint256(10)**decimals, "Amount should not exceed 1 million"); + function getTokens(uint256 _amount, address _recipient) public returns(bool) { + 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); @@ -44,7 +43,7 @@ contract PolyTokenFaucet { * @param _value The amount of token to be transferred * @return Whether the transfer was successful or not */ - function transfer(address _to, uint256 _value) public returns (bool) { + function transfer(address _to, uint256 _value) public returns(bool) { balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); @@ -58,7 +57,7 @@ contract PolyTokenFaucet { * @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) { + function transferFrom(address _from, address _to, uint256 _value) public returns(bool) { require(_to != address(0), "Invalid address"); require(_value <= balances[_from], "Insufficient tokens transferable"); require(_value <= allowed[_from][msg.sender], "Insufficient tokens allowable"); @@ -75,7 +74,7 @@ contract PolyTokenFaucet { * @param _owner The address from which the balance will be retrieved * @return The balance */ - function balanceOf(address _owner) public view returns (uint256 balance) { + function balanceOf(address _owner) public view returns(uint256 balance) { return balances[_owner]; } @@ -85,7 +84,7 @@ contract PolyTokenFaucet { * @param _value The amount of tokens to be approved for transfer * @return Whether the approval was successful or not */ - function approve(address _spender, uint256 _value) public returns (bool) { + function approve(address _spender, uint256 _value) public returns(bool) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; @@ -96,11 +95,11 @@ contract PolyTokenFaucet { * @param _spender The address of the account able to transfer the tokens * @return Amount of remaining tokens allowed to be spent */ - function allowance(address _owner, address _spender) public view returns (uint256 remaining) { + function allowance(address _owner, address _spender) public view returns(uint256 remaining) { return allowed[_owner][_spender]; } - function totalSupply() public view returns (uint256) { + function totalSupply() public view returns(uint256) { return totalSupply_; } @@ -113,15 +112,8 @@ contract PolyTokenFaucet { * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. */ - function increaseApproval( - address _spender, - uint _addedValue - ) - public - returns (bool) - { - allowed[msg.sender][_spender] = ( - allowed[msg.sender][_spender].add(_addedValue)); + function increaseApproval(address _spender, uint _addedValue) public returns(bool) { + allowed[msg.sender][_spender] = (allowed[msg.sender][_spender].add(_addedValue)); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } @@ -136,13 +128,7 @@ contract PolyTokenFaucet { * @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) - { + function decreaseApproval(address _spender, uint _subtractedValue) public returns(bool) { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; diff --git a/contracts/mocks/SecurityTokenRegistryMock.sol b/contracts/mocks/SecurityTokenRegistryMock.sol index d0a6de099..2ec9d8edd 100644 --- a/contracts/mocks/SecurityTokenRegistryMock.sol +++ b/contracts/mocks/SecurityTokenRegistryMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../SecurityTokenRegistry.sol"; @@ -6,11 +6,10 @@ import "../SecurityTokenRegistry.sol"; * @title Registry contract for issuers to register their security tokens */ contract SecurityTokenRegistryMock is SecurityTokenRegistry { - /// @notice It is a dummy function - /// Alert! Alert! Do not use it for the mainnet release - function changeTheDeployedAddress(string _ticker, address _newSecurityTokenAddress) public { + /// Alert! Alert! Do NOT use it for the mainnet release + function changeTheDeployedAddress(string memory _ticker, address _newSecurityTokenAddress) public { set(Encoder.getKey("tickerToSecurityToken", _ticker), _newSecurityTokenAddress); - } - + } + } diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index f9fad0c4e..47c7cd280 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -1,9 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/STO/DummySTOFactory.sol"; contract TestSTOFactory is DummySTOFactory { - /** * @notice Constructor * @param _setupCost Setup cost of the module @@ -11,8 +10,14 @@ contract TestSTOFactory is DummySTOFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) { version = "1.0.0"; name = "TestSTO"; @@ -25,14 +30,14 @@ contract TestSTOFactory is DummySTOFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Test STO - you can mint tokens at will"; } /** * @notice Gets the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Test"; availableTags[1] = "Non-refundable"; diff --git a/contracts/modules/Burn/IBurn.sol b/contracts/modules/Burn/IBurn.sol index 7a84a802b..64a9b7de9 100644 --- a/contracts/modules/Burn/IBurn.sol +++ b/contracts/modules/Burn/IBurn.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface to be implemented by all checkpoint modules diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 9d2bcef8a..e54aa27fa 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -5,7 +5,7 @@ * 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; +pragma solidity ^0.5.0; import "./ICheckpoint.sol"; import "./DividendCheckpointStorage.sol"; @@ -39,7 +39,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @notice Init function i.e generalise function to maintain the structure of the module contract * @return bytes4 */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(0); } @@ -47,7 +47,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @notice Return the default excluded addresses * @return List of excluded addresses */ - function getDefaultExcluded() external view returns (address[]) { + function getDefaultExcluded() external view returns(address[] memory) { return excluded; } @@ -55,7 +55,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @notice Creates a checkpoint on the security token * @return Checkpoint ID */ - function createCheckpoint() public withPerm(CHECKPOINT) returns (uint256) { + function createCheckpoint() public withPerm(CHECKPOINT) returns(uint256) { return ISecurityToken(securityToken).createCheckpoint(); } @@ -63,12 +63,12 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @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) { + function setDefaultExcluded(address[] memory _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"); + require(_excluded[j] != address(0), "Invalid address"); for (uint256 i = j + 1; i < _excluded.length; i++) { - require (_excluded[j] != _excluded[i], "Duplicate exclude address"); + require(_excluded[j] != _excluded[i], "Duplicate exclude address"); } } excluded = _excluded; @@ -81,12 +81,12 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @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) { + function setWithholding(address[] memory _investors, uint256[] memory _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"); + require(_withholding[i] <= 10 ** 18, "Incorrect withholding tax"); withholdingTax[_investors[i]] = _withholding[i]; } } @@ -96,8 +96,8 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @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"); + function setWithholdingFixed(address[] memory _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++) { @@ -112,11 +112,11 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { */ function pushDividendPaymentToAddresses( uint256 _dividendIndex, - address[] _payees - ) - public - withPerm(DISTRIBUTE) - validDividendIndex(_dividendIndex) + address payable[] memory _payees + ) + public + withPerm(DISTRIBUTE) + validDividendIndex(_dividendIndex) { Dividend storage dividend = dividends[_dividendIndex]; for (uint256 i = 0; i < _payees.length; i++) { @@ -136,16 +136,15 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { uint256 _dividendIndex, uint256 _start, uint256 _iterations - ) - public - withPerm(DISTRIBUTE) - validDividendIndex(_dividendIndex) + ) public + withPerm(DISTRIBUTE) + validDividendIndex(_dividendIndex) { Dividend storage dividend = dividends[_dividendIndex]; address[] memory investors = ISecurityToken(securityToken).getInvestors(); uint256 numberInvestors = Math.min(investors.length, _start.add(_iterations)); for (uint256 i = _start; i < numberInvestors; i++) { - address payee = investors[i]; + address payable payee = address(uint160(investors[i])); if ((!dividend.claimed[payee]) && (!dividend.dividendExcluded[payee])) { _payDividend(payee, dividend, _dividendIndex); } @@ -156,8 +155,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) { Dividend storage dividend = dividends[_dividendIndex]; require(!dividend.claimed[msg.sender], "Dividend already claimed"); require(!dividend.dividendExcluded[msg.sender], "msg.sender excluded from Dividend"); @@ -170,7 +168,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @param _dividend Storage with previously issued dividends * @param _dividendIndex Dividend to pay */ - function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal; + function _payDividend(address payable _payee, Dividend storage _dividend, uint256 _dividendIndex) internal; /** * @notice Issuer can reclaim remaining unclaimed dividend amounts, for expired dividends @@ -192,7 +190,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { } 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)); + uint256 withheld = claim.mul(withholdingTax[_payee]).div(uint256(10 ** 18)); return (claim, withheld); } @@ -201,9 +199,9 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @param _checkpointId Checkpoint id to query * @return uint256[] */ - function getDividendIndex(uint256 _checkpointId) public view returns(uint256[]) { + function getDividendIndex(uint256 _checkpointId) public view returns(uint256[] memory) { uint256 counter = 0; - for(uint256 i = 0; i < dividends.length; i++) { + for (uint256 i = 0; i < dividends.length; i++) { if (dividends[i].checkpointId == _checkpointId) { counter++; } @@ -211,7 +209,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { uint256[] memory index = new uint256[](counter); counter = 0; - for(uint256 j = 0; j < dividends.length; j++) { + for (uint256 j = 0; j < dividends.length; j++) { if (dividends[j].checkpointId == _checkpointId) { index[counter] = j; counter++; @@ -230,7 +228,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { * @notice Return the permissions flag that are associated with this module * @return bytes32 array */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](2); allPermissions[0] = DISTRIBUTE; allPermissions[1] = MANAGE; diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index 4cf1f2838..fa2f2793f 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -1,11 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @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"; @@ -15,16 +14,16 @@ contract DividendCheckpointStorage { 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) - bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + 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 + 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 } @@ -35,9 +34,9 @@ contract DividendCheckpointStorage { address[] public excluded; // Mapping from address to withholding tax as a percentage * 10**16 - mapping (address => uint256) public withholdingTax; + mapping(address => uint256) public withholdingTax; // Total amount of ETH withheld per investor - mapping (address => uint256) public investorWithheld; + mapping(address => uint256) public investorWithheld; } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index 6f1f21428..fecf21f8f 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./DividendCheckpoint.sol"; import "./ERC20DividendCheckpointStorage.sol"; @@ -23,19 +23,8 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec 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 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, @@ -47,9 +36,8 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @@ -61,14 +49,14 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec * @param _name Name/Title for identification */ function createDividend( - uint256 _maturity, - uint256 _expiry, - address _token, - uint256 _amount, + uint256 _maturity, + uint256 _expiry, + address _token, + uint256 _amount, bytes32 _name - ) - external - withPerm(MANAGE) + ) + external + withPerm(MANAGE) { createDividendWithExclusions(_maturity, _expiry, _token, _amount, excluded, _name); } @@ -89,9 +77,9 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec uint256 _amount, uint256 _checkpointId, bytes32 _name - ) - external - withPerm(MANAGE) + ) + external + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, excluded, _name); } @@ -110,11 +98,11 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec uint256 _expiry, address _token, uint256 _amount, - address[] _excluded, + address[] memory _excluded, bytes32 _name - ) - public - withPerm(MANAGE) + ) + public + withPerm(MANAGE) { uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, checkpointId, _excluded, _name); @@ -136,11 +124,11 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec address _token, uint256 _amount, uint256 _checkpointId, - address[] _excluded, + address[] memory _excluded, bytes32 _name - ) - public - withPerm(MANAGE) + ) + public + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _token, _amount, _checkpointId, _excluded, _name); } @@ -161,10 +149,10 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec address _token, uint256 _amount, uint256 _checkpointId, - address[] _excluded, + address[] memory _excluded, bytes32 _name - ) - internal + ) + internal { ISecurityToken securityTokenInstance = ISecurityToken(securityToken); require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); @@ -180,23 +168,23 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec 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 - ) + 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(_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; @@ -220,11 +208,22 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec uint256 currentSupply, uint256 dividendIndex, bytes32 _name - ) - internal + ) + internal { /*solium-disable-next-line security/no-block-members*/ - emit ERC20DividendDeposited(msg.sender, _checkpointId, now, _maturity, _expiry, _token, _amount, currentSupply, dividendIndex, _name); + emit ERC20DividendDeposited( + msg.sender, + _checkpointId, + now, + _maturity, + _expiry, + _token, + _amount, + currentSupply, + dividendIndex, + _name + ); } /** @@ -233,7 +232,7 @@ contract ERC20DividendCheckpoint is ERC20DividendCheckpointStorage, DividendChec * @param _dividend Storage with previously issued dividends * @param _dividendIndex Dividend to pay */ - function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { + function _payDividend(address payable _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); _dividend.claimed[_payee] = true; _dividend.claimedAmount = claim.add(_dividend.claimedAmount); diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 502ad6b80..b9b83ef0d 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../proxy/ERC20DividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; @@ -7,7 +7,6 @@ import "../ModuleFactory.sol"; * @title Factory for deploying ERC20DividendCheckpoint module */ contract ERC20DividendCheckpointFactory is ModuleFactory { - address public logicContract; /** @@ -17,8 +16,14 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -34,9 +39,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 calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); - address erc20DividendCheckpoint = new ERC20DividendCheckpointProxy(msg.sender, polyToken, logicContract); + address erc20DividendCheckpoint = address(new ERC20DividendCheckpointProxy(msg.sender, polyToken, logicContract)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; @@ -45,7 +55,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 4; return res; @@ -54,14 +64,14 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Create ERC20 dividend to be paid out to token holders based on their balances at dividend creation time"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](3); availableTags[0] = "ERC20"; availableTags[1] = "Dividend"; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol index 29401f8d9..1c6bca68c 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol @@ -1,11 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title It holds the storage variables related to ERC20DividendCheckpoint module */ contract ERC20DividendCheckpointStorage { - // Mapping to token address for each dividend - mapping (uint256 => address) public dividendTokens; + mapping(uint256 => address) public dividendTokens; } diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol index eee93e587..30ac0e724 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./DividendCheckpoint.sol"; import "../../interfaces/IOwnable.sol"; @@ -29,9 +29,8 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @@ -56,10 +55,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _expiry, uint256 _checkpointId, bytes32 _name - ) - external - payable - withPerm(MANAGE) + ) + external + payable + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, excluded, _name); } @@ -74,12 +73,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint { function createDividendWithExclusions( uint256 _maturity, uint256 _expiry, - address[] _excluded, + address[] memory _excluded, bytes32 _name - ) - public - payable - withPerm(MANAGE) + ) + public + payable + withPerm(MANAGE) { uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); _createDividendWithCheckpointAndExclusions(_maturity, _expiry, checkpointId, _excluded, _name); @@ -97,12 +96,12 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _maturity, uint256 _expiry, uint256 _checkpointId, - address[] _excluded, + address[] memory _excluded, bytes32 _name - ) - public - payable - withPerm(MANAGE) + ) + public + payable + withPerm(MANAGE) { _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, _excluded, _name); } @@ -119,10 +118,10 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 _maturity, uint256 _expiry, uint256 _checkpointId, - address[] _excluded, + address[] memory _excluded, bytes32 _name - ) - internal + ) + internal { require(_excluded.length <= EXCLUDED_ADDRESS_LIMIT, "Too many addresses excluded"); require(_expiry > _maturity, "Expiry is before maturity"); @@ -135,23 +134,23 @@ contract EtherDividendCheckpoint is DividendCheckpoint { uint256 currentSupply = ISecurityToken(securityToken).totalSupplyAt(_checkpointId); uint256 excludedSupply = 0; dividends.push( - Dividend( - _checkpointId, - now, /*solium-disable-line security/no-block-members*/ - _maturity, - _expiry, - msg.value, - 0, - 0, - false, - 0, - 0, - _name - ) + Dividend( + _checkpointId, + now, /*solium-disable-line security/no-block-members*/ + _maturity, + _expiry, + msg.value, + 0, + 0, + false, + 0, + 0, + _name + ) ); for (uint256 j = 0; j < _excluded.length; j++) { - require (_excluded[j] != address(0), "Invalid address"); + require(_excluded[j] != address(0), "Invalid address"); require(!dividends[dividendIndex].dividendExcluded[_excluded[j]], "duped exclude address"); excludedSupply = excludedSupply.add(ISecurityToken(securityToken).balanceOfAt(_excluded[j], _checkpointId)); dividends[dividendIndex].dividendExcluded[_excluded[j]] = true; @@ -167,7 +166,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { * @param _dividend storage with previously issued dividends * @param _dividendIndex Dividend to pay */ - function _payDividend(address _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { + function _payDividend(address payable _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { (uint256 claim, uint256 withheld) = calculateDividend(_dividendIndex, _payee); _dividend.claimed[_payee] = true; uint256 claimAfterWithheld = claim.sub(withheld); @@ -197,7 +196,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { Dividend storage dividend = dividends[_dividendIndex]; dividend.reclaimed = true; uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); - address owner = IOwnable(securityToken).owner(); + address payable owner = address(uint160(IOwnable(securityToken).owner())); owner.transfer(remainingAmount); emit EtherDividendReclaimed(owner, _dividendIndex, remainingAmount); } @@ -211,7 +210,7 @@ contract EtherDividendCheckpoint is DividendCheckpoint { Dividend storage dividend = dividends[_dividendIndex]; uint256 remainingWithheld = dividend.dividendWithheld.sub(dividend.dividendWithheldReclaimed); dividend.dividendWithheldReclaimed = dividend.dividendWithheld; - address owner = IOwnable(securityToken).owner(); + address payable owner = address(uint160(IOwnable(securityToken).owner())); owner.transfer(remainingWithheld); emit EtherDividendWithholdingWithdrawn(owner, _dividendIndex, remainingWithheld); } diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index f51677d00..92b1ba7f3 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../proxy/EtherDividendCheckpointProxy.sol"; import "../ModuleFactory.sol"; @@ -7,7 +7,6 @@ import "../ModuleFactory.sol"; * @title Factory for deploying EtherDividendCheckpoint module */ contract EtherDividendCheckpointFactory is ModuleFactory { - address public logicContract; /** @@ -17,8 +16,14 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -34,9 +39,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 calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); - address ethDividendCheckpoint = new EtherDividendCheckpointProxy(msg.sender, polyToken, logicContract); + address ethDividendCheckpoint = address(new EtherDividendCheckpointProxy(msg.sender, polyToken, logicContract)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; @@ -45,7 +55,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 4; return res; @@ -54,14 +64,14 @@ contract EtherDividendCheckpointFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Create a dividend which will be paid out to token holders proportionally according to their balances at the point the dividend is created"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](3); availableTags[0] = "ETH"; availableTags[1] = "Checkpoint"; diff --git a/contracts/modules/Checkpoint/ICheckpoint.sol b/contracts/modules/Checkpoint/ICheckpoint.sol index f2a7417b2..f7b10b77d 100644 --- a/contracts/modules/Checkpoint/ICheckpoint.sol +++ b/contracts/modules/Checkpoint/ICheckpoint.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface to be implemented by all checkpoint modules diff --git a/contracts/modules/Experimental/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol index 5e34bbaba..9b86ef82f 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../Burn/IBurn.sol"; import "../../Module.sol"; @@ -11,7 +11,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract TrackedRedemption is IBurn, Module { using SafeMath for uint256; - mapping (address => uint256) redeemedTokens; + mapping(address => uint256) redeemedTokens; event Redeemed(address _investor, uint256 _value, uint256 _timestamp); @@ -19,15 +19,14 @@ contract TrackedRedemption is IBurn, Module { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(0); } @@ -45,7 +44,7 @@ contract TrackedRedemption is IBurn, Module { /** * @notice Returns the permissions flag that are associated with CountTransferManager */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](0); return allPermissions; } diff --git a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol index f2b18ee4d..729bfe854 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./TrackedRedemption.sol"; import "../../ModuleFactory.sol"; @@ -7,15 +7,19 @@ import "../../ModuleFactory.sol"; * @title Factory for deploying GeneralTransferManager module */ contract TrackedRedemptionFactory is ModuleFactory { - /** * @notice Constructor * @param _setupCost Setup cost of module * @param _usageCost Usage cost of module * @param _subscriptionCost Monthly cost of module */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "TrackedRedemption"; @@ -29,9 +33,14 @@ contract TrackedRedemptionFactory 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 calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); - address trackedRedemption = new TrackedRedemption(msg.sender, polyToken); + address trackedRedemption = address(new TrackedRedemption(msg.sender, polyToken)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(trackedRedemption), getName(), address(this), msg.sender, setupCost, now); return address(trackedRedemption); @@ -40,7 +49,7 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 5; return res; @@ -49,14 +58,14 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Allows an investor to redeem security tokens which are tracked by this module"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Redemption"; availableTags[1] = "Tracked"; diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index e838f78e6..e2aed863f 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./../../Checkpoint/ICheckpoint.sol"; import "../../TransferManager/TransferManager.sol"; @@ -24,7 +24,7 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { bytes32[] public names; - mapping (bytes32 => Schedule) public schedules; + mapping(bytes32 => Schedule) public schedules; event AddSchedule(bytes32 _name, uint256 _startTime, uint256 _interval, uint256 _timestamp); event RemoveSchedule(bytes32 _name, uint256 _timestamp); @@ -33,15 +33,14 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(0); } @@ -79,13 +78,21 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { 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) external returns(Result) { + function verifyTransfer( + address, /* _from */ + address, /* _to */ + uint256, /* _amount */ + bytes calldata, /* _data */ + bool _isTransfer + ) + external + returns(Result) + { require(_isTransfer == false || msg.sender == securityToken, "Sender is not owner"); if (paused || !_isTransfer) { return Result.NA; @@ -98,16 +105,16 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { * @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 - ); + function getSchedule(bytes32 _name) external view returns( + bytes32, + uint256, + uint256, + uint256, + uint256[] memory, + uint256[] memory, + uint256[] memory + ){ + return (schedules[_name].name, schedules[_name].startTime, schedules[_name].nextTime, schedules[_name].interval, schedules[_name].checkpointIds, schedules[_name].timestamps, schedules[_name].periods); } /** @@ -133,7 +140,7 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { /** * @notice manually triggers update outside of transfer request for all schedules (can be used to reduce user gas costs) */ - function updateAll() onlyOwner external { + function updateAll() external onlyOwner { _updateAll(); } @@ -147,7 +154,7 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { /** * @notice Return the permissions flag that are associated with CountTransferManager */ - function getPermissions() view external returns(bytes32[]) { + function getPermissions() external view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](0); return allPermissions; } diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol index 6ef2fc34a..e2b9e57c4 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./ScheduledCheckpoint.sol"; import "../../ModuleFactory.sol"; @@ -7,15 +7,19 @@ import "../../ModuleFactory.sol"; * @title Factory for deploying EtherDividendCheckpoint module */ contract ScheduledCheckpointFactory is ModuleFactory { - /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "ScheduledCheckpoint"; @@ -29,9 +33,14 @@ contract ScheduledCheckpointFactory 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 calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); - address scheduledCheckpoint = new ScheduledCheckpoint(msg.sender, polyToken); + address scheduledCheckpoint = address(new ScheduledCheckpoint(msg.sender, polyToken)); emit GenerateModuleFromFactory(scheduledCheckpoint, getName(), address(this), msg.sender, setupCost, now); return scheduledCheckpoint; } @@ -39,7 +48,7 @@ contract ScheduledCheckpointFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](2); res[0] = 4; res[1] = 2; @@ -56,42 +65,42 @@ contract ScheduledCheckpointFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() external view returns(string) { + function getDescription() external view returns(string memory) { return description; } /** * @notice Get the title of the Module */ - function getTitle() external view returns(string) { + function getTitle() external view returns(string memory) { return title; } /** * @notice Get the version of the Module */ - function getVersion() external view returns(string) { + function getVersion() external view returns(string memory) { return version; } /** * @notice Get the setup cost of the module */ - function getSetupCost() external view returns (uint256) { + function getSetupCost() external view returns(uint256) { return setupCost; } /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { 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[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Scheduled"; availableTags[1] = "Checkpoint"; diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol index a4f6b95f6..5d0ac2307 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol @@ -1,11 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./../../TransferManager/TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - contract LockupVolumeRestrictionTM is TransferManager { - using SafeMath for uint256; // permission definition @@ -21,7 +19,7 @@ contract LockupVolumeRestrictionTM is TransferManager { } // maps user addresses to an array of lockups for that user - mapping (address => LockUp[]) internal lockUps; + mapping(address => LockUp[]) internal lockUps; event AddNewLockUp( address indexed userAddress, @@ -54,19 +52,25 @@ contract LockupVolumeRestrictionTM is TransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) - public - Module(_securityToken, _polyToken) - { - } + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @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) external returns(Result) { + function verifyTransfer( + address _from, + address, /* _to*/ + uint256 _amount, + bytes calldata, /* _data */ + bool _isTransfer + ) + external + 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 @@ -89,7 +93,10 @@ contract LockupVolumeRestrictionTM is TransferManager { uint _releaseFrequencySeconds, uint _startTime, uint _totalAmount - ) public withPerm(ADMIN) { + ) + public + withPerm(ADMIN) + { uint256 startTime = _startTime; _checkLockUpParams(_lockUpPeriodSeconds, _releaseFrequencySeconds, _totalAmount); @@ -120,17 +127,17 @@ contract LockupVolumeRestrictionTM is TransferManager { * @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) { + address[] calldata _userAddresses, + uint[] calldata _lockUpPeriodsSeconds, + uint[] calldata _releaseFrequenciesSeconds, + uint[] calldata _startTimes, + uint[] calldata _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, + _userAddresses.length == _lockUpPeriodsSeconds.length && _userAddresses.length == _releaseFrequenciesSeconds.length && _userAddresses.length == _startTimes.length && _userAddresses.length == _totalAmounts.length, /*solium-disable-line operator-whitespace*/ /*solium-disable-line operator-whitespace*/ "Input array length mismatch" ); @@ -184,7 +191,10 @@ contract LockupVolumeRestrictionTM is TransferManager { uint _releaseFrequencySeconds, uint _startTime, uint _totalAmount - ) public withPerm(ADMIN) { + ) + public + withPerm(ADMIN) + { require(_lockUpIndex < lockUps[_userAddress].length, "Array out of bounds exception"); uint256 startTime = _startTime; @@ -205,21 +215,14 @@ contract LockupVolumeRestrictionTM is TransferManager { lockUps[_userAddress][_lockUpIndex].alreadyWithdrawn ); - emit ModifyLockUp( - _userAddress, - _lockUpPeriodSeconds, - _releaseFrequencySeconds, - startTime, - _totalAmount, - _lockUpIndex - ); + 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) { + function getLockUpsLength(address _userAddress) public view returns(uint) { return lockUps[_userAddress].length; } @@ -228,43 +231,30 @@ contract LockupVolumeRestrictionTM is TransferManager { * @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, 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 - ); + 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) { + 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 - ]; + uint[3] memory tokenSums = [uint256(0), uint256(0), uint256(0)]; // allowed amount right now // total locked up, ever // already withdrawn, ever // loop over the user's lock ups for (uint i = 0; i < userLockUps.length; i++) { @@ -315,8 +305,8 @@ contract LockupVolumeRestrictionTM is TransferManager { 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]; + for (uint256 i = 0; i < userLockUps.length; i++) { + LockUp storage aLockUp = userLockUps[i]; // tokenSums[0] is allowed sum if (allowedAmountPerLockup[i] >= tokenSums[0]) { @@ -342,7 +332,11 @@ contract LockupVolumeRestrictionTM is TransferManager { uint amount, uint totalSum, uint alreadyWithdrawnSum - ) internal view returns (Result) { + ) + 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); @@ -353,7 +347,6 @@ contract LockupVolumeRestrictionTM is TransferManager { 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) @@ -395,14 +388,14 @@ contract LockupVolumeRestrictionTM is TransferManager { /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + 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[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = ADMIN; return allPermissions; diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol index d751f0b1c..a677cccdf 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./../../ModuleFactory.sol"; import "./LockupVolumeRestrictionTM.sol"; @@ -7,15 +7,19 @@ import "./LockupVolumeRestrictionTM.sol"; * @title Factory for deploying ManualApprovalTransferManager module */ contract LockupVolumeRestrictionTMFactory is ModuleFactory { - /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "LockupVolumeRestrictionTM"; @@ -25,11 +29,16 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { 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) { + function deploy( + bytes calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ @@ -41,7 +50,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { * @notice Type of the Module factory * @return uint8 */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 2; return res; @@ -50,19 +59,18 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters."; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Volume"; availableTags[1] = "Transfer Restriction"; return availableTags; } - } diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol index 8dd1d3a66..431408336 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./../../TransferManager/TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -10,7 +10,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract SingleTradeVolumeRestrictionTM is TransferManager { using SafeMath for uint256; - bytes32 constant public ADMIN = "ADMIN"; + bytes32 public constant ADMIN = "ADMIN"; bool public isTransferLimitInPercentage; @@ -46,9 +46,7 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor(address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { } @@ -60,11 +58,11 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { address _from, address /* _to */, uint256 _amount, - bytes /* _data */, + bytes calldata /* _data */, bool /* _isTransfer */ - ) - external - returns(Result) + ) + external + returns(Result) { bool validTransfer; @@ -75,12 +73,14 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { } if (isTransferLimitInPercentage) { - if(specialTransferLimitsInPercentages[_from] > 0) { - validTransfer = (_amount.mul(10**18).div(ISecurityToken(securityToken).totalSupply())) <= specialTransferLimitsInPercentages[_from]; + 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; + validTransfer = (_amount.mul(10 ** 18).div(ISecurityToken(securityToken).totalSupply())) <= globalTransferLimitInPercentage; } - } else { + } else { if (specialTransferLimitsInTokens[_from] > 0) { validTransfer = _amount <= specialTransferLimitsInTokens[_from]; } else { @@ -100,7 +100,10 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { bool _isTransferLimitInPercentage, uint256 _globalTransferLimitInPercentageOrToken, bool _allowPrimaryIssuance - ) public onlyFactory { + ) + public + onlyFactory + { isTransferLimitInPercentage = _isTransferLimitInPercentage; if (isTransferLimitInPercentage) { changeGlobalLimitInPercentage(_globalTransferLimitInPercentageOrToken); @@ -165,7 +168,10 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { */ 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]"); + require( + _newGlobalTransferLimitInPercentage > 0 && _newGlobalTransferLimitInPercentage <= 100 * 10 ** 16, + "Limit not within [0,100]" + ); emit GlobalTransferLimitInPercentageSet(_newGlobalTransferLimitInPercentage, globalTransferLimitInPercentage); globalTransferLimitInPercentage = _newGlobalTransferLimitInPercentage; @@ -195,7 +201,7 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * @notice Adds an array of exempt wallet * @param _wallets array of exempt wallet addresses */ - function addExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { + function addExemptWalletMulti(address[] memory _wallets) public withPerm(ADMIN) { require(_wallets.length > 0, "Wallets cannot be empty"); for (uint256 i = 0; i < _wallets.length; i++) { addExemptWallet(_wallets[i]); @@ -206,7 +212,7 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * @notice Removes an array of exempt wallet * @param _wallets array of exempt wallet addresses */ - function removeExemptWalletMulti(address[] _wallets) public withPerm(ADMIN) { + function removeExemptWalletMulti(address[] memory _wallets) public withPerm(ADMIN) { require(_wallets.length > 0, "Wallets cannot be empty"); for (uint256 i = 0; i < _wallets.length; i++) { removeExemptWallet(_wallets[i]); @@ -240,7 +246,6 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { emit TransferLimitInPercentageSet(_wallet, _transferLimitInPercentage); } - /** * @notice Removes transfer limit set in percentage for a wallet * @param _wallet wallet address @@ -267,10 +272,10 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * @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) { + function setTransferLimitInTokensMulti(address[] memory _wallets, uint[] memory _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++ ) { + for (uint256 i = 0; i < _wallets.length; i++) { setTransferLimitInTokens(_wallets[i], _transferLimits[i]); } } @@ -282,7 +287,10 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * 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) { + function setTransferLimitInPercentageMulti( + address[] memory _wallets, + uint[] memory _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++) { @@ -294,7 +302,7 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * @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) { + function removeTransferLimitInTokensMulti(address[] memory _wallets) public withPerm(ADMIN) { require(_wallets.length > 0, "Wallets cannot be empty"); for (uint i = 0; i < _wallets.length; i++) { removeTransferLimitInTokens(_wallets[i]); @@ -305,7 +313,7 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { * @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) { + function removeTransferLimitInPercentageMulti(address[] memory _wallets) public withPerm(ADMIN) { require(_wallets.length > 0, "Wallets cannot be empty"); for (uint i = 0; i < _wallets.length; i++) { removeTransferLimitInPercentage(_wallets[i]); @@ -315,14 +323,14 @@ contract SingleTradeVolumeRestrictionTM is TransferManager { /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + 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[]) { + function getPermissions() public view returns(bytes32[] memory) { 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 index 4e2b1ff1b..d00a32bf0 100644 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./../../ModuleFactory.sol"; import "./SingleTradeVolumeRestrictionTM.sol"; @@ -8,16 +8,19 @@ import "../../../libraries/Util.sol"; * @title Factory for deploying SingleTradeVolumeRestrictionManager */ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { - - /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor(uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "SingleTradeVolumeRestrictionTM"; @@ -31,12 +34,14 @@ contract SingleTradeVolumeRestrictionTMFactory 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 calldata _data) external returns(address) { address polyToken = _takeFee(); SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender, polyToken); require(Util.getSig(_data) == singleTradeVolumeRestrictionManager.getInitFunction(), "Provided data is not valid"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(singleTradeVolumeRestrictionManager).call(_data), "Unsuccessful call"); + (success, ) = address(singleTradeVolumeRestrictionManager).call(_data); + require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(singleTradeVolumeRestrictionManager), getName(), address(this), msg.sender, setupCost, now); return address(singleTradeVolumeRestrictionManager); @@ -46,7 +51,7 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { * @notice Get the types of the Module factory * @return uint8[] */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 2; return res; @@ -56,7 +61,7 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { * @notice Get the Instructions that help to use the module * @return string */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { /*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"; } @@ -65,7 +70,7 @@ contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { * @notice Get the tags related to the module factory * @return bytes32[] */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](3); availableTags[0] = "Single Trade"; availableTags[1] = "Transfer"; diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index aae15670a..e2db5f6d9 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../RegistryUpdater.sol"; import "../interfaces/IModule.sol"; @@ -12,40 +12,41 @@ import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; * @notice Contract is abstract */ contract Module is IModule, ModuleStorage { - /** * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - ModuleStorage(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public ModuleStorage(_securityToken, _polyToken) { + } //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"); + require( + isOwner || isFactory || ISecurityToken(securityToken).checkPermission(msg.sender, address(this), _perm), + "Permission check failed" + ); _; } - modifier onlyOwner { + modifier onlyOwner() { require(msg.sender == Ownable(securityToken).owner(), "Sender is not owner"); _; } - modifier onlyFactory { + modifier onlyFactory() { require(msg.sender == factory, "Sender is not factory"); _; } - modifier onlyFactoryOwner { + modifier onlyFactoryOwner() { require(msg.sender == Ownable(factory).owner(), "Sender is not factory owner"); _; } - modifier onlyFactoryOrOwner { + modifier onlyFactoryOrOwner() { require((msg.sender == Ownable(securityToken).owner()) || (msg.sender == factory), "Sender is not factory or owner"); _; } diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index adc4432b6..9cf1ffcc4 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../RegistryUpdater.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; @@ -11,7 +11,6 @@ import "../libraries/VersionUtils.sol"; * @notice Contract is abstract */ contract ModuleFactory is IModuleFactory, Ownable { - uint256 public usageCost; uint256 public monthlySubscriptionCost; @@ -43,7 +42,7 @@ contract ModuleFactory is IModuleFactory, Ownable { /** * @notice Constructor */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public { + constructor(uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public { setupCost = _setupCost; usageCost = _usageCost; monthlySubscriptionCost = _subscriptionCost; @@ -81,7 +80,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @notice Updates the title of the ModuleFactory * @param _newTitle New Title that will replace the old one. */ - function changeTitle(string _newTitle) public onlyOwner { + function changeTitle(string memory _newTitle) public onlyOwner { require(bytes(_newTitle).length > 0, "Invalid title"); title = _newTitle; } @@ -90,7 +89,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @notice Updates the description of the ModuleFactory * @param _newDesc New description that will replace the old one. */ - function changeDescription(string _newDesc) public onlyOwner { + function changeDescription(string memory _newDesc) public onlyOwner { require(bytes(_newDesc).length > 0, "Invalid description"); description = _newDesc; } @@ -100,7 +99,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _newName New name that will replace the old one. */ function changeName(bytes32 _newName) public onlyOwner { - require(_newName != bytes32(0),"Invalid name"); + require(_newName != bytes32(0), "Invalid name"); name = _newName; } @@ -108,7 +107,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @notice Updates the version of the ModuleFactory * @param _newVersion New name that will replace the old one. */ - function changeVersion(string _newVersion) public onlyOwner { + function changeVersion(string memory _newVersion) public onlyOwner { require(bytes(_newVersion).length > 0, "Invalid version"); version = _newVersion; } @@ -118,10 +117,11 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _boundType Type of bound * @param _newVersion new version array */ - function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external onlyOwner { + function changeSTVersionBounds(string calldata _boundType, uint8[] calldata _newVersion) external onlyOwner { require( - keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("lowerBound")) || - keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("upperBound")), + 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); @@ -137,7 +137,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @notice Used to get the lower bound * @return lower bound */ - function getLowerSTVersionBounds() external view returns(uint8[]) { + function getLowerSTVersionBounds() external view returns(uint8[] memory) { return VersionUtils.unpack(compatibleSTVersionRange["lowerBound"]); } @@ -145,30 +145,29 @@ contract ModuleFactory is IModuleFactory, Ownable { * @notice Used to get the upper bound * @return upper bound */ - function getUpperSTVersionBounds() external view returns(uint8[]) { + function getUpperSTVersionBounds() external view returns(uint8[] memory) { return VersionUtils.unpack(compatibleSTVersionRange["upperBound"]); } /** * @notice Get the setup cost of the module */ - function getSetupCost() external view returns (uint256) { + function getSetupCost() external view returns(uint256) { return setupCost; } - /** + /** * @notice Get the name of the Module */ - function getName() public view returns (bytes32) { + function getName() public view returns(bytes32) { return name; } - function _takeFee() internal returns (address) { + function _takeFee() internal returns(address) { address polyToken = RegistryUpdater(msg.sender).polyToken(); require(polyToken != address(0), "Invalid POLY token"); if (setupCost > 0) { - require(IERC20(polyToken).transferFrom(msg.sender, owner(), setupCost), - "Insufficient allowance for module fee"); + require(IERC20(polyToken).transferFrom(msg.sender, owner(), setupCost), "Insufficient allowance for module fee"); } return polyToken; } diff --git a/contracts/modules/ModuleStorage.sol b/contracts/modules/ModuleStorage.sol index fd9307934..720c653fb 100644 --- a/contracts/modules/ModuleStorage.sol +++ b/contracts/modules/ModuleStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; @@ -7,7 +7,6 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; * @notice Contract is abstract */ contract ModuleStorage { - address public factory; address public securityToken; @@ -21,7 +20,7 @@ contract ModuleStorage { * @param _securityToken Address of the security token * @param _polyAddress Address of the polytoken */ - constructor (address _securityToken, address _polyAddress) public { + constructor(address _securityToken, address _polyAddress) public { securityToken = _securityToken; factory = msg.sender; polyToken = IERC20(_polyAddress); diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 6c41a25ce..4587785f0 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./IPermissionManager.sol"; import "../Module.sol"; @@ -14,18 +14,16 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio /// Used to notify when delegate is added in permission manager contract event AddDelegate(address indexed _delegate, bytes32 _details, uint256 _timestamp); - /// @notice constructor - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** * @notice Init function i.e generalise function to maintain the structure of the module contract * @return bytes4 */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(0); } @@ -39,8 +37,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns(bool) { if (delegateDetails[_delegate] != bytes32(0)) { return perms[_module][_delegate][_perm]; - } else - return false; + } else return false; } /** @@ -83,8 +80,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio if (delegateDetails[_potentialDelegate] != bytes32(0)) { return true; - } else - return false; + } else return false; } /** @@ -95,15 +91,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio * @param _valid Bool flag use to switch on/off the permission * @return bool */ - function changePermission( - address _delegate, - address _module, - bytes32 _perm, - bool _valid - ) - public - withPerm(CHANGE_PERMISSION) - { + function changePermission(address _delegate, address _module, bytes32 _perm, bool _valid) public withPerm(CHANGE_PERMISSION) { require(_delegate != address(0), "invalid address"); _changePermission(_delegate, _module, _perm, _valid); } @@ -118,18 +106,18 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio */ function changePermissionMulti( address _delegate, - address[] _modules, - bytes32[] _perms, - bool[] _valids - ) - external - withPerm(CHANGE_PERMISSION) + address[] calldata _modules, + bytes32[] calldata _perms, + bool[] calldata _valids + ) + external + withPerm(CHANGE_PERMISSION) { require(_delegate != address(0), "invalid address"); require(_modules.length > 0, "0 length is not allowed"); require(_modules.length == _perms.length, "Array length mismatch"); require(_valids.length == _perms.length, "Array length mismatch"); - for(uint256 i = 0; i < _perms.length; i++) { + for (uint256 i = 0; i < _perms.length; i++) { _changePermission(_delegate, _modules[i], _perms[i], _valids[i]); } } @@ -140,7 +128,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio * @param _perm Permission flag * @return address[] */ - function getAllDelegatesWithPerm(address _module, bytes32 _perm) external view returns(address[]) { + function getAllDelegatesWithPerm(address _module, bytes32 _perm) external view returns(address[] memory) { uint256 counter = 0; uint256 i = 0; for (i = 0; i < allDelegates.length; i++) { @@ -151,7 +139,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio address[] memory allDelegatesWithPerm = new address[](counter); counter = 0; for (i = 0; i < allDelegates.length; i++) { - if (perms[_module][allDelegates[i]][_perm]){ + if (perms[_module][allDelegates[i]][_perm]) { allDelegatesWithPerm[counter] = allDelegates[i]; counter++; } @@ -167,18 +155,21 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio * @return address[] the address array of Modules this delegate has permission * @return bytes32[] the permission array of the corresponding Modules */ - function getAllModulesAndPermsFromTypes(address _delegate, uint8[] _types) external view returns(address[], bytes32[]) { + function getAllModulesAndPermsFromTypes(address _delegate, uint8[] calldata _types) external view returns( + address[] memory, + bytes32[] memory + ) { uint256 counter = 0; // loop through _types and get their modules from securityToken->getModulesByType for (uint256 i = 0; i < _types.length; i++) { address[] memory _currentTypeModules = ISecurityToken(securityToken).getModulesByType(_types[i]); // loop through each modules to get their perms from IModule->getPermissions - for (uint256 j = 0; j < _currentTypeModules.length; j++){ + for (uint256 j = 0; j < _currentTypeModules.length; j++) { bytes32[] memory _allModulePerms = IModule(_currentTypeModules[j]).getPermissions(); // loop through each perm, if it is true, push results into arrays for (uint256 k = 0; k < _allModulePerms.length; k++) { if (perms[_currentTypeModules[j]][_delegate][_allModulePerms[k]]) { - counter ++; + counter++; } } } @@ -188,11 +179,11 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio bytes32[] memory _allPerms = new bytes32[](counter); counter = 0; - for (i = 0; i < _types.length; i++){ - _currentTypeModules = ISecurityToken(securityToken).getModulesByType(_types[i]); - for (j = 0; j < _currentTypeModules.length; j++) { - _allModulePerms = IModule(_currentTypeModules[j]).getPermissions(); - for (k = 0; k < _allModulePerms.length; k++) { + for (uint256 i = 0; i < _types.length; i++) { + address[] memory _currentTypeModules = ISecurityToken(securityToken).getModulesByType(_types[i]); + for (uint256 j = 0; j < _currentTypeModules.length; j++) { + bytes32[] memory _allModulePerms = IModule(_currentTypeModules[j]).getPermissions(); + for (uint256 k = 0; k < _allModulePerms.length; k++) { if (perms[_currentTypeModules[j]][_delegate][_allModulePerms[k]]) { _allModules[counter] = _currentTypeModules[j]; _allPerms[counter] = _allModulePerms[k]; @@ -202,7 +193,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio } } - return(_allModules, _allPerms); + return (_allModules, _allPerms); } /** @@ -213,14 +204,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio * @param _valid Bool flag use to switch on/off the permission * @return bool */ - function _changePermission( - address _delegate, - address _module, - bytes32 _perm, - bool _valid - ) - internal - { + function _changePermission(address _delegate, address _module, bytes32 _perm, bool _valid) internal { perms[_module][_delegate][_perm] = _valid; /*solium-disable-next-line security/no-block-members*/ emit ChangePermission(_delegate, _module, _perm, _valid, now); @@ -230,7 +214,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio * @notice Used to get all delegates * @return address[] */ - function getAllDelegates() external view returns(address[]) { + function getAllDelegates() external view returns(address[] memory) { return allDelegates; } @@ -238,7 +222,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio * @notice Returns the Permission flag related the `this` contract * @return Array of permission flags */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = CHANGE_PERMISSION; return allPermissions; diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index 77792b2b7..f1b52dd9f 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../proxy/GeneralPermissionManagerProxy.sol"; @@ -17,8 +17,14 @@ contract GeneralPermissionManagerFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -34,9 +40,14 @@ contract GeneralPermissionManagerFactory 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 calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); - address permissionManager = new GeneralPermissionManagerProxy(msg.sender, polyToken, logicContract); + address permissionManager = address(new GeneralPermissionManagerProxy(msg.sender, polyToken, logicContract)); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); return permissionManager; @@ -45,7 +56,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 1; return res; @@ -54,7 +65,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { /*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."; } @@ -62,7 +73,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](0); return availableTags; } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol index 3a1a43513..cc50bc871 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the GeneralPermissionManager storage diff --git a/contracts/modules/PermissionManager/IPermissionManager.sol b/contracts/modules/PermissionManager/IPermissionManager.sol index d9b78944d..f1fdc69b5 100644 --- a/contracts/modules/PermissionManager/IPermissionManager.sol +++ b/contracts/modules/PermissionManager/IPermissionManager.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Interface to be implemented by all permission manager modules */ interface IPermissionManager { - /** * @notice Used to check the permission on delegate corresponds to module contract address * @param _delegate Ethereum address of the delegate @@ -42,13 +41,7 @@ interface IPermissionManager { * @param _valid Bool flag use to switch on/off the permission * @return bool */ - function changePermission( - address _delegate, - address _module, - bytes32 _perm, - bool _valid - ) - external; + function changePermission(address _delegate, address _module, bytes32 _perm, bool _valid) external; /** * @notice Used to change one or more permissions for a single delegate at once @@ -60,11 +53,10 @@ interface IPermissionManager { */ function changePermissionMulti( address _delegate, - address[] _modules, - bytes32[] _perms, - bool[] _valids - ) - external; + address[] calldata _modules, + bytes32[] calldata _perms, + bool[] calldata _valids + ) external; /** * @notice Used to return all delegates with a given permission and module @@ -72,9 +64,9 @@ interface IPermissionManager { * @param _perm Permission flag * @return address[] */ - function getAllDelegatesWithPerm(address _module, bytes32 _perm) external view returns(address[]); + function getAllDelegatesWithPerm(address _module, bytes32 _perm) external view returns(address[] memory); - /** + /** * @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 @@ -82,18 +74,21 @@ interface IPermissionManager { * @return address[] the address array of Modules this delegate has permission * @return bytes32[] the permission array of the corresponding Modules */ - function getAllModulesAndPermsFromTypes(address _delegate, uint8[] _types) external view returns(address[], bytes32[]); + function getAllModulesAndPermsFromTypes(address _delegate, uint8[] calldata _types) external view returns( + address[] memory, + bytes32[] memory + ); /** * @notice Used to get the Permission flag related the `this` contract * @return Array of permission flags */ - function getPermissions() external view returns(bytes32[]); + function getPermissions() external view returns(bytes32[] memory); /** * @notice Used to get all delegates * @return address[] */ - function getAllDelegates() external view returns(address[]); + function getAllDelegates() external view returns(address[] memory); } diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 1cdc08984..3c7adcd0b 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; @@ -23,16 +23,15 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { event SetAllowBeneficialInvestments(bool _allowed); - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } ////////////////////////////////// /** * @notice fallback function ***DO NOT OVERRIDE*** */ - function () external payable { + function() external payable { buyTokens(msg.sender); } @@ -50,11 +49,11 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { uint256 _endTime, uint256 _cap, uint256 _rate, - FundRaiseType[] _fundRaiseTypes, - address _fundsReceiver - ) - public - onlyFactory + FundRaiseType[] memory _fundRaiseTypes, + address payable _fundsReceiver + ) + public + onlyFactory { require(endTime == 0, "Already configured"); require(_rate > 0, "Rate of token should be greater than 0"); @@ -74,7 +73,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(keccak256("configure(uint256,uint256,uint256,uint256,uint8[],address)")); } @@ -112,7 +111,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @notice low level token purchase * @param _investedPOLY Amount of POLY invested */ - function buyTokensWithPoly(uint256 _investedPOLY) public nonReentrant{ + function buyTokensWithPoly(uint256 _investedPOLY) public nonReentrant { require(!paused, "Should not be paused"); require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "Mode of investment is not POLY"); uint256 refund = _processTx(msg.sender, _investedPOLY); @@ -124,7 +123,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @notice Checks whether the cap has been reached. * @return bool Whether the cap was reached */ - function capReached() public view returns (bool) { + function capReached() public view returns(bool) { return totalTokensSold >= cap; } @@ -138,7 +137,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { /** * @notice Return the permissions flag that are associated with STO */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](0); return allPermissions; } @@ -155,16 +154,9 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @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 ( - startTime, - endTime, - cap, - rate, - (fundRaiseTypes[uint8(FundRaiseType.POLY)]) ? fundsRaised[uint8(FundRaiseType.POLY)]: fundsRaised[uint8(FundRaiseType.ETH)], - investorCount, - totalTokensSold, - (fundRaiseTypes[uint8(FundRaiseType.POLY)]) - ); + return (startTime, endTime, cap, rate, (fundRaiseTypes[uint8(FundRaiseType.POLY)]) ? fundsRaised[uint8( + FundRaiseType.POLY + )] : fundsRaised[uint8(FundRaiseType.ETH)], investorCount, totalTokensSold, (fundRaiseTypes[uint8(FundRaiseType.POLY)])); } // ----------------------------------------- @@ -176,7 +168,6 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @param _investedAmount Value in wei involved in the purchase */ function _processTx(address _beneficiary, uint256 _investedAmount) internal returns(uint256 refund) { - _preValidatePurchase(_beneficiary, _investedAmount); // calculate token amount to be created uint256 tokens; @@ -217,8 +208,11 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @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 + function _postValidatePurchase( + address, /*_beneficiary*/ + uint256 /*_investedAmount*/ + ) internal pure { + // optional override } /** @@ -249,8 +243,11 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @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 + function _updatePurchasingState( + address, /*_beneficiary*/ + uint256 _investedAmount + ) internal pure { + _investedAmount = 0; //yolo } /** @@ -259,7 +256,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @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) { + function _getTokenAmount(uint256 _investedAmount) internal view returns(uint256 _tokens, uint256 _refund) { _tokens = _investedAmount.mul(rate); _tokens = _tokens.div(uint256(10) ** 18); uint256 granularity = ISecurityToken(securityToken).granularity(); diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 24bf5de06..06090758c 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -19,8 +19,14 @@ contract CappedSTOFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -32,27 +38,30 @@ contract CappedSTOFactory is ModuleFactory { logicContract = _logicContract; } - /** + /** * @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) { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function - CappedSTOProxy cappedSTO = new CappedSTOProxy(msg.sender, polyToken, logicContract); + address cappedSTO = address(new CappedSTOProxy(msg.sender, polyToken, logicContract)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IBoot(cappedSTO).getInitFunction(), "Invalid data"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(cappedSTO).call(_data), "Unsuccessfull call"); + (success, ) = cappedSTO.call(_data); + require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(cappedSTO), getName(), address(this), msg.sender, setupCost, now); - return address(cappedSTO); + emit GenerateModuleFromFactory(cappedSTO, getName(), address(this), msg.sender, setupCost, now); + return cappedSTO; } /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 3; return res; @@ -61,7 +70,7 @@ contract CappedSTOFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { /*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)"; } @@ -69,7 +78,7 @@ contract CappedSTOFactory is ModuleFactory { /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Capped"; availableTags[1] = "Non-refundable"; diff --git a/contracts/modules/STO/CappedSTOStorage.sol b/contracts/modules/STO/CappedSTOStorage.sol index 51afb048e..7ddeea403 100644 --- a/contracts/modules/STO/CappedSTOStorage.sol +++ b/contracts/modules/STO/CappedSTOStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the CappedSTO storage diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index cdd770ac7..5a4e5e560 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; @@ -15,9 +15,8 @@ contract DummySTO is DummySTOStorage, STO { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @@ -27,7 +26,7 @@ contract DummySTO is DummySTOStorage, STO { * @param _cap Maximum No. of tokens for sale * @param _someString Any string that contails the details */ - function configure(uint256 _startTime, uint256 _endTime, uint256 _cap, string _someString) public onlyFactory { + function configure(uint256 _startTime, uint256 _endTime, uint256 _cap, string memory _someString) public onlyFactory { startTime = _startTime; endTime = _endTime; cap = _cap; @@ -37,7 +36,7 @@ contract DummySTO is DummySTOStorage, STO { /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(keccak256("configure(uint256,uint256,uint256,string)")); } @@ -55,27 +54,27 @@ contract DummySTO is DummySTOStorage, STO { } //TODO: Add SafeMath maybe investors[_investor] = investors[_investor] + _amount; - emit GenerateTokens (_investor, _amount); + emit GenerateTokens(_investor, _amount); } /** * @notice Returns the total no. of investors */ - function getNumberInvestors() public view returns (uint256) { + function getNumberInvestors() public view returns(uint256) { return investorCount; } /** * @notice Returns the total no. of investors */ - function getTokensSold() external view returns (uint256) { + function getTokensSold() external view returns(uint256) { return 0; } /** * @notice Returns the permissions flag that are associated with STO */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = ADMIN; return allPermissions; diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index ac3e3cb79..ee84a4251 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -19,8 +19,14 @@ contract DummySTOFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "DummySTO"; @@ -33,25 +39,28 @@ contract DummySTOFactory is ModuleFactory { /** * @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) { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function - DummySTOProxy dummySTO = new DummySTOProxy(msg.sender, polyToken, logicContract); + address dummySTO = address(new DummySTOProxy(msg.sender, polyToken, logicContract)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IBoot(dummySTO).getInitFunction(), "Invalid data"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(dummySTO).call(_data), "Unsuccessfull call"); + (success, ) = dummySTO.call(_data); + require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(dummySTO), getName(), address(this), msg.sender, setupCost, now); - return address(dummySTO); + emit GenerateModuleFromFactory(dummySTO, getName(), address(this), msg.sender, setupCost, now); + return dummySTO; } /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 3; return res; @@ -60,14 +69,14 @@ contract DummySTOFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Dummy STO - you can mint tokens at will"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Dummy"; availableTags[1] = "Non-refundable"; diff --git a/contracts/modules/STO/DummySTOStorage.sol b/contracts/modules/STO/DummySTOStorage.sol index 5e841b261..0979974ec 100644 --- a/contracts/modules/STO/DummySTOStorage.sol +++ b/contracts/modules/STO/DummySTOStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the DummySTO storage diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index dbc0bccfb..09f4a1ce9 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; @@ -17,9 +17,8 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @@ -34,28 +33,28 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { /** * @notice This function returns the signature of the configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(keccak256("configure(uint256)")); } /** * @notice Returns the total no. of investors */ - function getNumberInvestors() public view returns (uint256) { + function getNumberInvestors() public view returns(uint256) { return investorCount; } /** * @notice Returns the total no. of tokens sold */ - function getTokensSold() external view returns (uint256) { + function getTokensSold() external view returns(uint256) { return totalTokensSold; } /** * @notice Returns the permissions flag that are associated with STO */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = PRE_SALE_ADMIN; return allPermissions; @@ -73,9 +72,9 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { uint256 _amount, uint256 _etherContributed, uint256 _polyContributed - ) - public - withPerm(PRE_SALE_ADMIN) + ) + public + withPerm(PRE_SALE_ADMIN) { /*solium-disable-next-line security/no-block-members*/ require(now <= endTime, "Already passed Endtime"); @@ -99,13 +98,13 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { * @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) + address[] memory _investors, + uint256[] memory _amounts, + uint256[] memory _etherContributed, + uint256[] memory _polyContributed + ) + public + withPerm(PRE_SALE_ADMIN) { require(_investors.length == _amounts.length, "Mis-match in length of the arrays"); require(_etherContributed.length == _polyContributed.length, "Mis-match in length of the arrays"); diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index a1103ac0d..e3ae055d1 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -19,8 +19,14 @@ contract PreSaleSTOFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -37,23 +43,25 @@ contract PreSaleSTOFactory is ModuleFactory { * @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) { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function - PreSaleSTOProxy preSaleSTO = new PreSaleSTOProxy(msg.sender, polyToken, logicContract); + address preSaleSTO = address(new PreSaleSTOProxy(msg.sender, polyToken, logicContract)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IBoot(preSaleSTO).getInitFunction(), "Invalid data"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(preSaleSTO).call(_data), "Unsuccessfull call"); + (success, ) = preSaleSTO.call(_data); + require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(preSaleSTO), getName(), address(this), msg.sender, setupCost, now); - return address(preSaleSTO); + emit GenerateModuleFromFactory(preSaleSTO, getName(), address(this), msg.sender, setupCost, now); + return preSaleSTO; } /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 3; return res; @@ -62,14 +70,14 @@ contract PreSaleSTOFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Configure and track pre-sale token allocations"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](1); availableTags[0] = "Presale"; return availableTags; diff --git a/contracts/modules/STO/PreSaleSTOStorage.sol b/contracts/modules/STO/PreSaleSTOStorage.sol index 956284e3d..9c8ecc0a6 100644 --- a/contracts/modules/STO/PreSaleSTOStorage.sol +++ b/contracts/modules/STO/PreSaleSTOStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the PreSaleSTO storage diff --git a/contracts/modules/STO/STO.sol b/contracts/modules/STO/STO.sol index ef5d028a8..088e84951 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../Pausable.sol"; import "../Module.sol"; @@ -10,10 +10,10 @@ import "../../interfaces/ISTO.sol"; /** * @title Base abstract contract to be extended by all STO modules */ -contract STO is ISTO, STOStorage, Module, Pausable { +contract STO is ISTO, STOStorage, Module, Pausable { using SafeMath for uint256; - enum FundRaiseType { ETH, POLY, DAI } + enum FundRaiseType {ETH, POLY, DAI} // Event event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); @@ -33,7 +33,7 @@ contract STO is ISTO, STOStorage, Module, Pausable { /** * @notice Returns funds raised by the STO */ - function getRaised(FundRaiseType _fundRaiseType) public view returns (uint256) { + function getRaised(FundRaiseType _fundRaiseType) public view returns(uint256) { return fundsRaised[uint8(_fundRaiseType)]; } @@ -53,7 +53,7 @@ contract STO is ISTO, STOStorage, Module, Pausable { super._unpause(); } - function _setFundRaiseType(FundRaiseType[] _fundRaiseTypes) internal { + function _setFundRaiseType(FundRaiseType[] memory _fundRaiseTypes) internal { // FundRaiseType[] parameter type ensures only valid values for _fundRaiseTypes require(_fundRaiseTypes.length > 0, "Raise type is not specified"); fundRaiseTypes[uint8(FundRaiseType.ETH)] = false; diff --git a/contracts/modules/STO/STOStorage.sol b/contracts/modules/STO/STOStorage.sol index aecfaf3d7..96793d6d5 100644 --- a/contracts/modules/STO/STOStorage.sol +++ b/contracts/modules/STO/STOStorage.sol @@ -1,8 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Storage layout for the STO contract */ + contract STOStorage { mapping (uint8 => bool) public fundRaiseTypes; @@ -17,8 +18,8 @@ contract STOStorage { // Number of individual investors uint256 public investorCount; // Address where ETH & POLY funds are delivered - address public wallet; - // Final amount of tokens sold + address payable public wallet; + // 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 2c1bfced9..cea3a45f5 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./STO.sol"; import "../../interfaces/ISecurityToken.sol"; @@ -43,19 +43,9 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256 _rate ); event ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint256 _latestTier); - event SetAddresses( - address indexed _wallet, - address indexed _reserveWallet, - address indexed _usdToken - ); - event SetLimits( - uint256 _nonAccreditedLimitUSD, - uint256 _minimumInvestmentUSD - ); - event SetTimes( - uint256 _startTime, - uint256 _endTime - ); + event SetAddresses(address indexed _wallet, address indexed _reserveWallet, address indexed _usdToken); + event SetLimits(uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD); + event SetTimes(uint256 _startTime, uint256 _endTime); event SetTiers( uint256[] _ratePerTier, uint256[] _ratePerTierDiscountPoly, @@ -67,19 +57,19 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { // Modifiers // /////////////// - modifier validETH { + modifier validETH() { require(_getOracle(bytes32("ETH"), bytes32("USD")) != address(0), "Invalid Oracle"); require(fundRaiseTypes[uint8(FundRaiseType.ETH)], "ETH not allowed"); _; } - modifier validPOLY { + modifier validPOLY() { require(_getOracle(bytes32("POLY"), bytes32("USD")) != address(0), "Invalid Oracle"); require(fundRaiseTypes[uint8(FundRaiseType.POLY)], "POLY not allowed"); _; } - modifier validDAI { + modifier validDAI() { require(fundRaiseTypes[uint8(FundRaiseType.DAI)], "DAI not allowed"); _; } @@ -88,10 +78,8 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { // STO Configuration // /////////////////////// - constructor (address _securityToken, address _polyAddress) - public - Module(_securityToken, _polyAddress) - { + constructor(address _securityToken, address _polyAddress) public Module(_securityToken, _polyAddress) { + } /** @@ -110,17 +98,20 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { function configure( uint256 _startTime, uint256 _endTime, - uint256[] _ratePerTier, - uint256[] _ratePerTierDiscountPoly, - uint256[] _tokensPerTierTotal, - uint256[] _tokensPerTierDiscountPoly, + uint256[] memory _ratePerTier, + uint256[] memory _ratePerTierDiscountPoly, + uint256[] memory _tokensPerTierTotal, + uint256[] memory _tokensPerTierDiscountPoly, uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD, - FundRaiseType[] _fundRaiseTypes, - address _wallet, + FundRaiseType[] memory _fundRaiseTypes, + address payable _wallet, address _reserveWallet, address _usdToken - ) public onlyFactory { + ) + public + onlyFactory + { oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; require(endTime == 0, "Already configured"); @@ -136,7 +127,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @dev Modifies fund raise types * @param _fundRaiseTypes Array of fund raise types to allow */ - function modifyFunding(FundRaiseType[] _fundRaiseTypes) external onlyOwner { + function modifyFunding(FundRaiseType[] calldata _fundRaiseTypes) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _setFundRaiseType(_fundRaiseTypes); @@ -147,10 +138,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _nonAccreditedLimitUSD max non accredited invets limit * @param _minimumInvestmentUSD overall minimum investment limit */ - function modifyLimits( - uint256 _nonAccreditedLimitUSD, - uint256 _minimumInvestmentUSD - ) external onlyOwner { + function modifyLimits(uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); @@ -164,11 +152,14 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _tokensPerTierDiscountPoly Array of discounted tokens per tier */ function modifyTiers( - uint256[] _ratePerTier, - uint256[] _ratePerTierDiscountPoly, - uint256[] _tokensPerTierTotal, - uint256[] _tokensPerTierDiscountPoly - ) external onlyOwner { + uint256[] calldata _ratePerTier, + uint256[] calldata _ratePerTierDiscountPoly, + uint256[] calldata _tokensPerTierTotal, + uint256[] calldata _tokensPerTierDiscountPoly + ) + external + onlyOwner + { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); @@ -179,10 +170,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _startTime start time of sto * @param _endTime end time of sto */ - function modifyTimes( - uint256 _startTime, - uint256 _endTime - ) external onlyOwner { + function modifyTimes(uint256 _startTime, uint256 _endTime) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _modifyTimes(_startTime, _endTime); @@ -194,35 +182,29 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _reserveWallet Address of wallet where unsold tokens are sent * @param _usdToken Address of usd token (DAI) */ - function modifyAddresses( - address _wallet, - address _reserveWallet, - address _usdToken - ) external onlyOwner { + function modifyAddresses(address payable _wallet, address _reserveWallet, address _usdToken) external onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); _modifyAddresses(_wallet, _reserveWallet, _usdToken); } - function _modifyLimits( - uint256 _nonAccreditedLimitUSD, - uint256 _minimumInvestmentUSD - ) internal { + 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 { + uint256[] memory _ratePerTier, + uint256[] memory _ratePerTierDiscountPoly, + uint256[] memory _tokensPerTierTotal, + uint256[] memory _tokensPerTierDiscountPoly + ) + internal + { require(_tokensPerTierTotal.length > 0, "No tiers provided"); - require(_ratePerTier.length == _tokensPerTierTotal.length && - _ratePerTierDiscountPoly.length == _tokensPerTierTotal.length && - _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, + require( + _ratePerTier.length == _tokensPerTierTotal.length && _ratePerTierDiscountPoly.length == _tokensPerTierTotal.length && _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, "Tier data length mismatch" ); delete tiers; @@ -236,10 +218,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { emit SetTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); } - function _modifyTimes( - uint256 _startTime, - uint256 _endTime - ) internal { + function _modifyTimes(uint256 _startTime, uint256 _endTime) internal { /*solium-disable-next-line security/no-block-members*/ require((_endTime > _startTime) && (_startTime > now), "Invalid times"); startTime = _startTime; @@ -247,11 +226,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { emit SetTimes(_startTime, _endTime); } - function _modifyAddresses( - address _wallet, - address _reserveWallet, - address _usdToken - ) internal { + function _modifyAddresses(address payable _wallet, address _reserveWallet, address _usdToken) internal { require(_wallet != address(0) && _reserveWallet != address(0), "Invalid wallet"); if (fundRaiseTypes[uint8(FundRaiseType.DAI)]) { require(_usdToken != address(0), "Invalid usdToken"); @@ -295,7 +270,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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[] memory _investors, bool[] memory _accredited) public onlyOwner { require(_investors.length == _accredited.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { accredited[_investors[i]] = _accredited[i]; @@ -308,7 +283,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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[] memory _investors, uint256[] memory _nonAccreditedLimit) public onlyOwner { //nonAccreditedLimitUSDOverride require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { @@ -335,7 +310,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { /** * @notice fallback function - assumes ETH being invested */ - function () external payable { + function() external payable { buyWithETHRateLimited(msg.sender, 0); } @@ -418,11 +393,11 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256 _investmentValue, uint256 _rate, FundRaiseType _fundRaiseType - ) - internal - nonReentrant - whenNotPaused - returns(uint256 spentUSD, uint256 spentValue) + ) + internal + nonReentrant + whenNotPaused + returns(uint256 spentUSD, uint256 spentValue) { if (!allowBeneficialInvestments) { require(_beneficiary == msg.sender, "Beneficiary != funder"); @@ -435,22 +410,19 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { bool gotoNextTier; uint256 tempSpentUSD; // Update current tier if needed - if (currentTier != i) - currentTier = i; + if (currentTier != i) currentTier = i; // If there are tokens remaining, process investment if (tiers[i].mintedTotal < tiers[i].tokenTotal) { (tempSpentUSD, gotoNextTier) = _calculateTier(_beneficiary, i, allowedUSD.sub(spentUSD), _fundRaiseType); spentUSD = spentUSD.add(tempSpentUSD); // If all funds have been spent, exit the loop - if (!gotoNextTier) - break; + if (!gotoNextTier) break; } } // Modify storage if (spentUSD > 0) { - if (investorInvestedUSD[_beneficiary] == 0) - investorCount = investorCount + 1; + if (investorInvestedUSD[_beneficiary] == 0) investorCount = investorCount + 1; investorInvestedUSD[_beneficiary] = investorInvestedUSD[_beneficiary].add(spentUSD); fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } @@ -464,16 +436,15 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @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 || _fundRaiseType == FundRaiseType.ETH, "Invalid raise type"); + function buyTokensView(address _beneficiary, uint256 _investmentValue, FundRaiseType _fundRaiseType) public view returns( + uint256 spentUSD, + uint256 spentValue, + uint256 tokensMinted + ) { + 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); @@ -489,8 +460,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { spentUSD = spentUSD.add(tempSpentUSD); tokensMinted = tokensMinted.add(tempTokensMinted); // If all funds have been spent, exit the loop - if (!gotoNextTier) - break; + if (!gotoNextTier) break; } } @@ -498,13 +468,13 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { } function _buyTokensChecks( - address _beneficiary, - uint256 _investmentValue, + address _beneficiary, + uint256 _investmentValue, uint256 investedUSD - ) - internal - view - returns(uint256 netInvestedUSD) + ) + internal + view + returns(uint256 netInvestedUSD) { require(isOpen(), "STO not open"); require(_investmentValue > 0, "No funds were sent"); @@ -516,20 +486,16 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { 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]); + if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) netInvestedUSD = investorLimitUSD.sub( + investorInvestedUSD[_beneficiary] + ); } } - function _calculateTier( - address _beneficiary, - uint256 _tier, - uint256 _investedUSD, - FundRaiseType _fundRaiseType - ) - internal - returns(uint256 spentUSD, bool gotoNextTier) - { + function _calculateTier(address _beneficiary, uint256 _tier, uint256 _investedUSD, FundRaiseType _fundRaiseType) internal returns( + uint256 spentUSD, + bool gotoNextTier + ) { // First purchase any discounted tokens if POLY investment uint256 tierSpentUSD; uint256 tierPurchasedTokens; @@ -539,36 +505,47 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { 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, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, totalRemaining, investedUSD, _tier); - else - (spentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, discountRemaining, investedUSD, _tier); + if (totalRemaining < discountRemaining) (spentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier( + _beneficiary, + tierData.rateDiscountPoly, + totalRemaining, + investedUSD, + _tier + ); + else (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); 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 && - (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) - ) { - (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), investedUSD, _tier); + if (investedUSD > 0 && tierData.tokenTotal.sub( + tierData.mintedTotal + ) > 0 && (_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); tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } } - function _calculateTierView( - uint256 _tier, - uint256 _investedUSD, - FundRaiseType _fundRaiseType - ) - internal - view - returns(uint256 spentUSD, bool gotoNextTier, uint256 tokensMinted) - { + 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; @@ -577,18 +554,23 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { 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); + 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 && - (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly) - ) { - (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTierAmount(tierData.rate, tierData.tokenTotal.sub(tierData.mintedTotal), _investedUSD); + if (_investedUSD > 0 && tierData.tokenTotal.sub( + tierData.mintedTotal.add(tokensMinted) + ) > 0 && (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly)) { + (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTierAmount( + tierData.rate, + tierData.tokenTotal.sub(tierData.mintedTotal), + _investedUSD + ); spentUSD = spentUSD.add(tierSpentUSD); tokensMinted = tokensMinted.add(tierPurchasedTokens); } @@ -600,9 +582,9 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256 _tierRemaining, uint256 _investedUSD, uint256 _tier - ) - internal - returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) + ) + internal + returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { (spentUSD, purchasedTokens, gotoNextTier) = _purchaseTierAmount(_tierPrice, _tierRemaining, _investedUSD); if (purchasedTokens > 0) { @@ -612,13 +594,13 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { } function _purchaseTierAmount( - uint256 _tierPrice, - uint256 _tierRemaining, + uint256 _tierPrice, + uint256 _tierRemaining, uint256 _investedUSD - ) - internal - view - returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) + ) + internal + view + returns(uint256 spentUSD,uint256 purchasedTokens,bool gotoNextTier) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); uint256 granularity = ISecurityToken(securityToken).granularity(); @@ -647,16 +629,12 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @return bool Whether the STO is accepting investments */ function isOpen() public view returns(bool) { - if (isFinalized) - return false; + if (isFinalized) return false; /*solium-disable-next-line security/no-block-members*/ - if (now < startTime) - return false; + if (now < startTime) return false; /*solium-disable-next-line security/no-block-members*/ - if (now >= endTime) - return false; - if (capReached()) - return false; + if (now >= endTime) return false; + if (capReached()) return false; return true; } @@ -664,7 +642,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice Checks whether the cap has been reached. * @return bool Whether the cap was reached */ - function capReached() public view returns (bool) { + function capReached() public view returns(bool) { if (isFinalized) { return (finalAmountReturned == 0); } @@ -675,13 +653,13 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @dev returns current conversion rate of funds * @param _fundRaiseType Fund raise type to get rate of */ - function getRate(FundRaiseType _fundRaiseType) public view returns (uint256) { + function getRate(FundRaiseType _fundRaiseType) public view returns(uint256) { if (_fundRaiseType == FundRaiseType.ETH) { 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) { - return 1 * 10**18; + return 1 * 10 ** 18; } else { revert("Incorrect funding"); } @@ -728,7 +706,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice Return the total no. of tokens minted * @return uint256 Total number of tokens minted */ - function getTokensMinted() public view returns (uint256) { + function getTokensMinted() public view returns(uint256) { uint256 tokensMinted; for (uint256 i = 0; i < tiers.length; i++) { tokensMinted = tokensMinted.add(tiers[i].mintedTotal); @@ -741,7 +719,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * 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) { + function getTokensSoldFor(FundRaiseType _fundRaiseType) public view returns(uint256) { uint256 tokensSold; for (uint256 i = 0; i < tiers.length; i++) { tokensSold = tokensSold.add(tiers[i].minted[uint8(_fundRaiseType)]); @@ -754,7 +732,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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) public view returns(uint256[] memory) { require(_tier < tiers.length, "Invalid tier"); uint256[] memory tokensMinted = new uint256[](3); tokensMinted[0] = tiers[_tier].minted[uint8(FundRaiseType.ETH)]; @@ -768,7 +746,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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) public view returns(uint256) { require(_tier < tiers.length, "Incorrect tier"); uint256 tokensSold; tokensSold = tokensSold.add(tiers[_tier].minted[uint8(FundRaiseType.ETH)]); @@ -781,14 +759,14 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice Return the total no. of tiers * @return uint256 Total number of tiers */ - function getNumberOfTiers() public view returns (uint256) { + function getNumberOfTiers() public view returns(uint256) { return tiers.length; } /** * @notice Return the permissions flag that are associated with STO */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](0); return allPermissions; } @@ -805,10 +783,21 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @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[]) { + function getSTODetails() public view returns( + uint256, + uint256, + uint256, + uint256[] memory, + uint256[] memory, + uint256, + uint256, + uint256, + bool[] memory + ) + { uint256[] memory cap = new uint256[](tiers.length); uint256[] memory rate = new uint256[](tiers.length); - for(uint256 i = 0; i < tiers.length; i++) { + for (uint256 i = 0; i < tiers.length; i++) { cap[i] = tiers[i].tokenTotal; rate[i] = tiers[i].rate; } @@ -833,11 +822,11 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice This function returns the signature of configure function * @return bytes4 Configure function signature */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return 0xb0ff041e; } - function _getOracle(bytes32 _currency, bytes32 _denominatedCurrency) internal view returns (address) { + function _getOracle(bytes32 _currency, bytes32 _denominatedCurrency) internal view returns(address) { return PolymathRegistry(RegistryUpdater(securityToken).polymathRegistry()).getAddress(oracleKeys[_currency][_denominatedCurrency]); } diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index b55b7bb81..4ad558144 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../interfaces/IBoot.sol"; import "../../proxy/USDTieredSTOProxy.sol"; @@ -9,7 +9,6 @@ import "../../libraries/Util.sol"; * @title Factory for deploying CappedSTO module */ contract USDTieredSTOFactory is ModuleFactory { - address public logicContract; /** @@ -18,8 +17,14 @@ contract USDTieredSTOFactory is ModuleFactory { * @param _usageCost Usage cost of the module * @param _subscriptionCost Subscription cost of the module */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "0x address is not allowed"); logicContract = _logicContract; @@ -32,17 +37,19 @@ contract USDTieredSTOFactory is ModuleFactory { 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) { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); - address usdTieredSTO = new USDTieredSTOProxy(msg.sender, polyToken, logicContract); + address usdTieredSTO = address(new USDTieredSTOProxy(msg.sender, polyToken, logicContract)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IBoot(usdTieredSTO).getInitFunction(), "Invalid data"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); + (success, ) = usdTieredSTO.call(_data); + require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, setupCost, now); return address(usdTieredSTO); @@ -51,7 +58,7 @@ contract USDTieredSTOFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 3; return res; @@ -60,14 +67,14 @@ contract USDTieredSTOFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Initialises a USD tiered STO."; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "USD"; availableTags[1] = "Tiered"; diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/modules/STO/USDTieredSTOStorage.sol index 919fd2900..a1c6f88ba 100644 --- a/contracts/modules/STO/USDTieredSTOStorage.sol +++ b/contracts/modules/STO/USDTieredSTOStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; @@ -6,34 +6,27 @@ import "openzeppelin-solidity/contracts/token/ERC20/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; - + 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; + mapping(bytes32 => mapping(bytes32 => string)) oracleKeys; IERC20 public usdToken; @@ -44,7 +37,7 @@ contract USDTieredSTOStorage { bool public isFinalized; // Address where ETH, POLY & DAI funds are delivered - address public wallet; + address payable public wallet; // Address of issuer reserve wallet for unsold tokens address public reserveWallet; @@ -56,19 +49,19 @@ contract USDTieredSTOStorage { uint256 public fundsRaisedUSD; // Amount in USD invested by each address - mapping (address => uint256) public investorInvestedUSD; + mapping(address => uint256) public investorInvestedUSD; // Amount in fund raise type invested by each investor - mapping (address => mapping (uint8 => uint256)) public investorInvested; + mapping(address => mapping(uint8 => uint256)) public investorInvested; // List of accredited investors - mapping (address => bool) public accredited; + 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; + mapping(address => uint256) public nonAccreditedLimitUSDOverride; // Minimum investable amount in USD uint256 public minimumInvestmentUSD; diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 64f4af91f..756a9ce7c 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./TransferManager.sol"; import "./CountTransferManagerStorage.sol"; @@ -14,10 +14,8 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) - public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @notice Used to verify the transfer transaction and prevent a transfer if it passes the allowed amount of token holders @@ -29,11 +27,11 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { address _from, address _to, uint256 _amount, - bytes /* _data */, + bytes calldata /* _data */, bool /* _isTransfer */ - ) - external - returns(Result) + ) + external + returns(Result) { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { @@ -68,14 +66,14 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(keccak256("configure(uint256)")); } /** * @notice Returns the permissions flag that are associated with CountTransferManager */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = ADMIN; return allPermissions; diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index b0b714fdc..f045fabc5 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -19,8 +19,13 @@ contract CountTransferManagerFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); version = "2.1.0"; @@ -37,22 +42,24 @@ contract CountTransferManagerFactory is ModuleFactory { * @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) { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); - CountTransferManagerProxy countTransferManager = new CountTransferManagerProxy(msg.sender, polyToken, logicContract); + address countTransferManager = address(new CountTransferManagerProxy(msg.sender, polyToken, logicContract)); require(Util.getSig(_data) == IBoot(countTransferManager).getInitFunction(), "Provided data is not valid"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(countTransferManager).call(_data), "Unsuccessful call"); + (success, ) = countTransferManager.call(_data); + require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(countTransferManager), getName(), address(this), msg.sender, setupCost, now); - return address(countTransferManager); + emit GenerateModuleFromFactory(countTransferManager, getName(), address(this), msg.sender, setupCost, now); + return countTransferManager; } /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 2; return res; @@ -61,14 +68,14 @@ contract CountTransferManagerFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Allows an issuer to restrict the total number of non-zero token holders"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Count"; availableTags[1] = "Transfer Restriction"; diff --git a/contracts/modules/TransferManager/CountTransferManagerStorage.sol b/contracts/modules/TransferManager/CountTransferManagerStorage.sol index 1c17e62d9..4a33663b1 100644 --- a/contracts/modules/TransferManager/CountTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/CountTransferManagerStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the CountTransferManager storage diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 36b742f90..ec88dadc9 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./TransferManager.sol"; import "./GeneralTransferManagerStorage.sol"; @@ -8,7 +8,6 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; * @title Transfer Manager module for core transfer validation functionality */ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManager { - using SafeMath for uint256; // Emit when Issuance address get changed @@ -45,16 +44,14 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) - public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(0); } @@ -141,7 +138,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _from Address of the sender * @param _to Address of the receiver */ - function verifyTransfer(address _from, address _to, uint256 /*_amount*/, bytes /* _data */, bool /* _isTransfer */) external returns(Result) { + function verifyTransfer( + address _from, + address _to, + uint256, /*_amount*/ + bytes calldata, /* _data */ + bool /* _isTransfer */ + ) external returns(Result) { if (!paused) { if (allowAllTransfers) { //All transfers allowed, regardless of whitelist @@ -171,8 +174,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage //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) && (adjustedFromTime <= uint64(now))) && (_onWhitelist(_to) && + (adjustedToTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -191,9 +194,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO - ) - public - withPerm(WHITELIST) + ) + public + withPerm(WHITELIST) { _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -206,15 +209,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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 - { + function _modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO) internal { require(_investor != address(0), "Invalid investor"); uint8 canBuyFromSTO = 0; if (_canBuyFromSTO) { @@ -236,11 +231,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _canBuyFromSTO An array of boolean values */ function modifyWhitelistMulti( - address[] _investors, - uint256[] _fromTimes, - uint256[] _toTimes, - uint256[] _expiryTimes, - bool[] _canBuyFromSTO + address[] memory _investors, + uint256[] memory _fromTimes, + uint256[] memory _toTimes, + uint256[] memory _expiryTimes, + bool[] memory _canBuyFromSTO ) public withPerm(WHITELIST) { require(_investors.length == _fromTimes.length, "Mismatched input lengths"); require(_fromTimes.length == _toTimes.length, "Mismatched input lengths"); @@ -277,7 +272,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint8 _v, bytes32 _r, bytes32 _s - ) public { + ) + public + { /*solium-disable-next-line security/no-block-members*/ require(_validFrom <= now, "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ @@ -336,16 +333,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage /** * @dev Returns list of all investors */ - function getInvestors() external view returns(address[]) { + function getInvestors() external view returns(address[] memory) { 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); + function getAllInvestorsData() external view returns( + address[] memory, + uint256[] memory fromTimes, + uint256[] memory toTimes, + uint256[] memory expiryTimes, + bool[] memory canBuyFromSTOs + ) { + (fromTimes, toTimes, expiryTimes, canBuyFromSTOs) = _investorsData(investors); return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs); } @@ -353,11 +355,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage /** * @dev Returns list of specified investors data */ - function getInvestorsData(address[] _investors) external view returns(uint256[], uint256[], uint256[], bool[]) { + function getInvestorsData(address[] calldata _investors) external view returns( + uint256[] memory, + uint256[] memory, + uint256[] memory, + bool[] memory + ) { return _investorsData(_investors); } - function _investorsData(address[] _investors) internal view returns(uint256[], uint256[], uint256[], bool[]) { + function _investorsData(address[] memory _investors) internal view returns( + uint256[] memory, + uint256[] memory, + uint256[] memory, + bool[] memory + ) { uint256[] memory fromTimes = new uint256[](_investors.length); uint256[] memory toTimes = new uint256[](_investors.length); uint256[] memory expiryTimes = new uint256[](_investors.length); @@ -378,7 +390,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage /** * @notice Return the permissions flag that are associated with general trnasfer manager */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](2); allPermissions[0] = WHITELIST; allPermissions[1] = FLAGS; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index cfebe557c..4c6d4a130 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../proxy/GeneralTransferManagerProxy.sol"; import "../ModuleFactory.sol"; @@ -7,7 +7,6 @@ import "../ModuleFactory.sol"; * @title Factory for deploying GeneralTransferManager module */ contract GeneralTransferManagerFactory is ModuleFactory { - address public logicContract; /** @@ -17,8 +16,14 @@ contract GeneralTransferManagerFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -30,24 +35,27 @@ contract GeneralTransferManagerFactory is ModuleFactory { logicContract = _logicContract; } - - /** + /** * @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) { - address polyToken= _takeFee(); - address generalTransferManager = new GeneralTransferManagerProxy(msg.sender, polyToken, logicContract); + function deploy( + bytes calldata /* _data */ + ) + external + returns(address) + { + address polyToken = _takeFee(); + GeneralTransferManagerProxy generalTransferManager = new GeneralTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); } - /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 2; return res; @@ -56,7 +64,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { /*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."; } @@ -64,12 +72,11 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() public view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "General"; availableTags[1] = "Transfer Restriction"; return availableTags; } - } diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol index cca7b5dd1..b9add9a57 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol @@ -1,10 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Transfer Manager module for core transfer validation functionality */ contract GeneralTransferManagerStorage { - //Address from which issuances come address public issuanceAddress = address(0); @@ -37,7 +36,7 @@ contract GeneralTransferManagerStorage { // An address can only send / receive tokens once their corresponding uint256 > block.number // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping (address => TimeRestriction) public whitelist; + mapping(address => TimeRestriction) public whitelist; // Map of used nonces by customer mapping(address => mapping(uint256 => bool)) public nonceMap; diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 382ffb486..3bc258c60 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -41,16 +41,14 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) - public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(0); } @@ -60,7 +58,16 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, * @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) external returns(Result) { + function verifyTransfer( + address _from, + address _to, + uint256 _amount, + bytes calldata, /* _data */ + bool _isTransfer + ) + external + 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 @@ -136,7 +143,7 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, /** * @notice Returns the permissions flag that are associated with ManualApproval transfer manager */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](1); allPermissions[0] = TRANSFER_APPROVAL; return allPermissions; diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 9a087adfd..ac4ac109c 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../proxy/ManualApprovalTransferManagerProxy.sol"; @@ -17,8 +17,14 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); version = "2.0.1"; @@ -30,13 +36,18 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { logicContract = _logicContract; } - /** + /** * @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 calldata /* _data */ + ) + external + returns(address) + { address polyToken = _takeFee(); - address manualTransferManager = new ManualApprovalTransferManagerProxy(msg.sender, polyToken, logicContract); + ManualApprovalTransferManagerProxy manualTransferManager = new ManualApprovalTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(manualTransferManager); @@ -45,7 +56,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 2; return res; @@ -54,7 +65,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { /*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."; } @@ -62,12 +73,11 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "ManualApproval"; availableTags[1] = "Transfer Restriction"; return availableTags; } - } diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol index cc7e55d49..6f94fbac6 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the ManualApprovalTransferManager storage diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index 3fe58381e..43c4a6f61 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -5,7 +5,7 @@ * higher than the intended limit. */ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -18,22 +18,15 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer using SafeMath for uint256; event ModifyHolderPercentage(uint256 _oldHolderPercentage, uint256 _newHolderPercentage); - event ModifyWhitelist( - address _investor, - uint256 _dateAdded, - address _addedBy, - bool _valid - ); + event ModifyWhitelist(address _investor, uint256 _dateAdded, address _addedBy, bool _valid); event SetAllowPrimaryIssuance(bool _allowPrimaryIssuance, uint256 _timestamp); /** * @notice Constructor * @param _securityToken Address of the security token */ - constructor (address _securityToken, address _polyToken) - public - Module(_securityToken, _polyToken) - { + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + } /** @notice Used to verify the transfer transaction and prevent a given account to end up with more tokens than allowed @@ -41,7 +34,16 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer * @param _to Address of the receiver * @param _amount The amount of tokens to transfer */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool /* _isTransfer */) external returns(Result) { + function verifyTransfer( + address _from, + address _to, + uint256 _amount, + bytes calldata, /* _data */ + bool /* _isTransfer */ + ) + external + returns(Result) + { if (!paused) { if (_from == address(0) && allowPrimaryIssuance) { return Result.NA; @@ -51,7 +53,7 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer return Result.NA; } uint256 newBalance = ISecurityToken(securityToken).balanceOf(_to).add(_amount); - if (newBalance.mul(uint256(10)**18).div(ISecurityToken(securityToken).totalSupply()) > maxHolderPercentage) { + if (newBalance.mul(uint256(10) ** 18).div(ISecurityToken(securityToken).totalSupply()) > maxHolderPercentage) { return Result.INVALID; } return Result.NA; @@ -71,7 +73,7 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer /** * @notice This function returns the signature of configure function */ - function getInitFunction() public pure returns (bytes4) { + function getInitFunction() public pure returns(bytes4) { return bytes4(keccak256("configure(uint256,bool)")); } @@ -100,7 +102,7 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer * @param _investors Array of the addresses to whitelist * @param _valids Array of boolean value to decide whether or not the address it to be added or removed from the whitelist */ - function modifyWhitelistMulti(address[] _investors, bool[] _valids) public withPerm(WHITELIST) { + function modifyWhitelistMulti(address[] memory _investors, bool[] memory _valids) public withPerm(WHITELIST) { require(_investors.length == _valids.length, "Input array length mis-match"); for (uint i = 0; i < _investors.length; i++) { modifyWhitelist(_investors[i], _valids[i]); @@ -121,7 +123,7 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer /** * @notice Return the permissions flag that are associated with Percentage transfer Manager */ - function getPermissions() public view returns(bytes32[]) { + function getPermissions() public view returns(bytes32[] memory) { bytes32[] memory allPermissions = new bytes32[](2); allPermissions[0] = WHITELIST; allPermissions[1] = ADMIN; diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index cecc759f7..4bed16c4d 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -19,8 +19,14 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @param _subscriptionCost Subscription cost of the module * @param _logicContract Contract address that contains the logic related to `description` */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor( + uint256 _setupCost, + uint256 _usageCost, + uint256 _subscriptionCost, + address _logicContract + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -37,15 +43,17 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @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) { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); - PercentageTransferManagerProxy percentageTransferManager = new PercentageTransferManagerProxy(msg.sender, polyToken, logicContract); + address percentageTransferManager = address(new PercentageTransferManagerProxy(msg.sender, polyToken, logicContract)); require(Util.getSig(_data) == IBoot(percentageTransferManager).getInitFunction(), "Provided data is not valid"); + bool success; /*solium-disable-next-line security/no-low-level-calls*/ - require(address(percentageTransferManager).call(_data), "Unsuccessful call"); + (success, ) = percentageTransferManager.call(_data); + require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(percentageTransferManager), getName(), address(this), msg.sender, setupCost, now); - return address(percentageTransferManager); + emit GenerateModuleFromFactory(percentageTransferManager, getName(), address(this), msg.sender, setupCost, now); + return percentageTransferManager; } @@ -53,7 +61,7 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @notice Type of the Module factory * @return uint8 */ - function getTypes() external view returns(uint8[]) { + function getTypes() external view returns(uint8[] memory) { uint8[] memory res = new uint8[](1); res[0] = 2; return res; @@ -62,14 +70,14 @@ contract PercentageTransferManagerFactory is ModuleFactory { /** * @notice Returns the instructions associated with the module */ - function getInstructions() external view returns(string) { + function getInstructions() external view returns(string memory) { return "Allows an issuer to restrict the total number of non-zero token holders"; } /** * @notice Get the tags related to the module factory */ - function getTags() external view returns(bytes32[]) { + function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Percentage"; availableTags[1] = "Transfer Restriction"; diff --git a/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol b/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol index 4656b200a..f2db59690 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @title Contract used to store layout for the PercentageTransferManager storage diff --git a/contracts/modules/TransferManager/TransferManager.sol b/contracts/modules/TransferManager/TransferManager.sol index 5d8cde83d..dd93f5c25 100644 --- a/contracts/modules/TransferManager/TransferManager.sol +++ b/contracts/modules/TransferManager/TransferManager.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../../Pausable.sol"; import "../Module.sol"; @@ -8,7 +8,6 @@ import "../../interfaces/ITransferManager.sol"; * @title Base abstract contract to be implemented by all Transfer Manager modules */ contract TransferManager is ITransferManager, TransferManagerEnums, Module, Pausable { - function unpause() public onlyOwner { super._unpause(); } diff --git a/contracts/oracles/MakerDAOOracle.sol b/contracts/oracles/MakerDAOOracle.sol index 51773cd7d..85da5d7b6 100644 --- a/contracts/oracles/MakerDAOOracle.sol +++ b/contracts/oracles/MakerDAOOracle.sol @@ -1,11 +1,10 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../interfaces/IOracle.sol"; import "../external/IMedianizer.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; contract MakerDAOOracle is IOracle, Ownable { - address public medianizer; address public currencyAddress; bytes32 public currencySymbol; @@ -24,7 +23,7 @@ contract MakerDAOOracle is IOracle, Ownable { * @param _currencyAddress Address of currency (0x0 for ETH) * @param _currencySymbol Symbol of currency */ - constructor (address _medianizer, address _currencyAddress, bytes32 _currencySymbol) public { + constructor(address _medianizer, address _currencyAddress, bytes32 _currencySymbol) public { medianizer = _medianizer; currencyAddress = _currencyAddress; currencySymbol = _currencySymbol; diff --git a/contracts/oracles/PolyOracle.sol b/contracts/oracles/PolyOracle.sol index 45f068a3e..f25cd7971 100644 --- a/contracts/oracles/PolyOracle.sol +++ b/contracts/oracles/PolyOracle.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../external/oraclizeAPI.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; @@ -11,7 +11,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { /*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 sanityBounds = 20 * 10 ** 16; uint256 public gasLimit = 100000; uint256 public oraclizeTimeTolerance = 5 minutes; uint256 public staleTime = 6 hours; @@ -20,10 +20,10 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { uint256 public latestUpdate; uint256 public latestScheduledUpdate; - mapping (bytes32 => uint256) public requestIds; - mapping (bytes32 => bool) public ignoreRequestIds; + mapping(bytes32 => uint256) public requestIds; + mapping(bytes32 => bool) public ignoreRequestIds; - mapping (address => bool) public admin; + mapping(address => bool) public admin; bool public freezeOracle; @@ -32,7 +32,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { event AdminSet(address _admin, bool _valid, uint256 _time); event StalePriceUpdate(bytes32 _queryId, uint256 _time, string _result); - modifier isAdminOrOwner { + modifier isAdminOrOwner() { require(admin[msg.sender] || msg.sender == owner(), "Address is not admin or owner"); _; } @@ -40,9 +40,9 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { /** * @notice Constructor - accepts ETH to initialise a balance for subsequent Oraclize queries */ - constructor() payable public { + constructor() public payable { // Use 50 gwei for now - oraclize_setCustomGasPrice(50*10**9); + oraclize_setCustomGasPrice(50 * 10 ** 9); } /** @@ -50,7 +50,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { * @param _requestId requestId corresponding to Oraclize query * @param _result data returned by Oraclize URL query */ - function __callback(bytes32 _requestId, string _result) public { + function __callback(bytes32 _requestId, string memory _result) public { require(msg.sender == oraclize_cbAddress(), "Only Oraclize can access this method"); require(!freezeOracle, "Oracle is frozen"); require(!ignoreRequestIds[_requestId], "Ignoring requestId"); @@ -63,7 +63,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { /*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); + 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"); @@ -77,7 +77,7 @@ 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) public payable isAdminOrOwner { + function schedulePriceUpdatesFixed(uint256[] memory _times) public payable isAdminOrOwner { bytes32 requestId; uint256 maximumScheduledUpdated; if (_times.length == 0) { @@ -155,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) public onlyOwner { + function setOracleURL(string memory _oracleURL) public onlyOwner { oracleURL = _oracleURL; } @@ -163,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) public onlyOwner { + function setOracleQueryType(string memory _oracleQueryType) public onlyOwner { oracleQueryType = _oracleQueryType; } @@ -215,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) public onlyOwner { + function setIgnoreRequestIds(bytes32[] memory _requestIds, bool[] memory _ignore) public onlyOwner { require(_requestIds.length == _ignore.length, "Incorrect parameter lengths"); for (uint256 i = 0; i < _requestIds.length; i++) { ignoreRequestIds[_requestIds[i]] = _ignore[i]; diff --git a/contracts/proxy/CappedSTOProxy.sol b/contracts/proxy/CappedSTOProxy.sol index 90084e5dc..1dc3604af 100644 --- a/contracts/proxy/CappedSTOProxy.sol +++ b/contracts/proxy/CappedSTOProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; @@ -18,9 +18,13 @@ contract CappedSTOProxy is CappedSTOStorage, STOStorage, ModuleStorage, Pausable * @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) + constructor( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { require( _implementation != address(0), diff --git a/contracts/proxy/CountTransferManagerProxy.sol b/contracts/proxy/CountTransferManagerProxy.sol index 2c030ba89..f91c32646 100644 --- a/contracts/proxy/CountTransferManagerProxy.sol +++ b/contracts/proxy/CountTransferManagerProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/TransferManager/CountTransferManagerStorage.sol"; import "./OwnedProxy.sol"; @@ -16,9 +16,13 @@ contract CountTransferManagerProxy is CountTransferManagerStorage, ModuleStorage * @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) + constructor ( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { require( _implementation != address(0), diff --git a/contracts/proxy/DummySTOProxy.sol b/contracts/proxy/DummySTOProxy.sol index 8ff44a887..71873c4d6 100644 --- a/contracts/proxy/DummySTOProxy.sol +++ b/contracts/proxy/DummySTOProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; @@ -18,9 +18,13 @@ contract DummySTOProxy is DummySTOStorage, STOStorage, ModuleStorage, Pausable, * @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) + constructor ( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { require( _implementation != address(0), diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol index 8839d30e1..efd4a1445 100644 --- a/contracts/proxy/ERC20DividendCheckpointProxy.sol +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; import "../modules/Checkpoint/DividendCheckpointStorage.sol"; @@ -10,21 +10,21 @@ 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) + constructor( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); + require(_implementation != address(0), "Implementation address should not be 0x"); __implementation = _implementation; } diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol index 40b1c1332..e03ccbbad 100644 --- a/contracts/proxy/EtherDividendCheckpointProxy.sol +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/Checkpoint/DividendCheckpointStorage.sol"; import "./OwnedProxy.sol"; @@ -9,21 +9,21 @@ 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) + constructor ( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); + require(_implementation != address(0), "Implementation address should not be 0x"); __implementation = _implementation; } diff --git a/contracts/proxy/GeneralPermissionManagerProxy.sol b/contracts/proxy/GeneralPermissionManagerProxy.sol index 8fff0061b..6273cf874 100644 --- a/contracts/proxy/GeneralPermissionManagerProxy.sol +++ b/contracts/proxy/GeneralPermissionManagerProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; @@ -18,9 +18,13 @@ contract GeneralPermissionManagerProxy is GeneralPermissionManagerStorage, Modul * @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) + constructor ( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { require( _implementation != address(0), diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol index cb9b69070..c8c8ddcc1 100644 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; import "./OwnedProxy.sol"; @@ -9,21 +9,21 @@ 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) + constructor( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { - require( - _implementation != address(0), - "Implementation address should not be 0x" - ); + require(_implementation != address(0), "Implementation address should not be 0x"); __implementation = _implementation; } diff --git a/contracts/proxy/ManualApprovalTransferManagerProxy.sol b/contracts/proxy/ManualApprovalTransferManagerProxy.sol index 366298d59..e3b4f6bc0 100644 --- a/contracts/proxy/ManualApprovalTransferManagerProxy.sol +++ b/contracts/proxy/ManualApprovalTransferManagerProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/TransferManager/ManualApprovalTransferManagerStorage.sol"; import "./OwnedProxy.sol"; @@ -16,9 +16,13 @@ contract ManualApprovalTransferManagerProxy is ManualApprovalTransferManagerStor * @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) + constructor ( + address _securityToken, + address _polyAddress, + address _implementation + ) + public + ModuleStorage(_securityToken, _polyAddress) { require( _implementation != address(0), diff --git a/contracts/proxy/ModuleRegistryProxy.sol b/contracts/proxy/ModuleRegistryProxy.sol index aea5a70c5..168905a56 100644 --- a/contracts/proxy/ModuleRegistryProxy.sol +++ b/contracts/proxy/ModuleRegistryProxy.sol @@ -1,9 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../storage/EternalStorage.sol"; import "./OwnedUpgradeabilityProxy.sol"; - /** * @title ModuleRegistryProxy * @dev This proxy holds the storage of the ModuleRegistry contract and delegates every call to the current implementation set. @@ -13,4 +12,4 @@ import "./OwnedUpgradeabilityProxy.sol"; /*solium-disable-next-line no-empty-blocks*/ contract ModuleRegistryProxy is EternalStorage, OwnedUpgradeabilityProxy { -} \ No newline at end of file +} diff --git a/contracts/proxy/OwnedProxy.sol b/contracts/proxy/OwnedProxy.sol index b75142fbe..efadc00cf 100644 --- a/contracts/proxy/OwnedProxy.sol +++ b/contracts/proxy/OwnedProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.5.0; import "./Proxy.sol"; @@ -7,7 +7,6 @@ import "./Proxy.sol"; * @dev This contract combines an upgradeability proxy with basic authorization control functionalities */ contract OwnedProxy is Proxy { - // Owner of the contract address private __owner; @@ -43,7 +42,7 @@ contract OwnedProxy is Proxy { * @dev Tells the address of the owner * @return the address of the owner */ - function _owner() internal view returns (address) { + function _owner() internal view returns(address) { return __owner; } @@ -58,7 +57,7 @@ contract OwnedProxy is Proxy { /** * @notice Internal function to provide the address of the implementation contract */ - function _implementation() internal view returns (address) { + function _implementation() internal view returns(address) { return __implementation; } @@ -66,7 +65,7 @@ contract OwnedProxy is Proxy { * @dev Tells the address of the proxy owner * @return the address of the proxy owner */ - function proxyOwner() external ifOwner returns (address) { + function proxyOwner() external ifOwner returns(address) { return _owner(); } @@ -74,7 +73,7 @@ contract OwnedProxy is Proxy { * @dev Tells the address of the current implementation * @return address of the current implementation */ - function implementation() external ifOwner returns (address) { + function implementation() external ifOwner returns(address) { return _implementation(); } diff --git a/contracts/proxy/OwnedUpgradeabilityProxy.sol b/contracts/proxy/OwnedUpgradeabilityProxy.sol index 7ec520630..314dc23cb 100644 --- a/contracts/proxy/OwnedUpgradeabilityProxy.sol +++ b/contracts/proxy/OwnedUpgradeabilityProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.18; +pragma solidity ^0.5.0; import "./UpgradeabilityProxy.sol"; @@ -7,7 +7,6 @@ import "./UpgradeabilityProxy.sol"; * @dev This contract combines an upgradeability proxy with basic authorization control functionalities */ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { - // Owner of the contract address private __upgradeabilityOwner; @@ -40,7 +39,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @dev Tells the address of the owner * @return the address of the owner */ - function _upgradeabilityOwner() internal view returns (address) { + function _upgradeabilityOwner() internal view returns(address) { return __upgradeabilityOwner; } @@ -55,7 +54,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { /** * @notice Internal function to provide the address of the implementation contract */ - function _implementation() internal view returns (address) { + function _implementation() internal view returns(address) { return __implementation; } @@ -63,7 +62,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @dev Tells the address of the proxy owner * @return the address of the proxy owner */ - function proxyOwner() external ifOwner returns (address) { + function proxyOwner() external ifOwner returns(address) { return _upgradeabilityOwner(); } @@ -71,7 +70,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @dev Tells the version name of the current implementation * @return string representing the name of the current version */ - function version() external ifOwner returns (string) { + function version() external ifOwner returns(string memory) { return __version; } @@ -79,7 +78,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @dev Tells the address of the current implementation * @return address of the current implementation */ - function implementation() external ifOwner returns (address) { + function implementation() external ifOwner returns(address) { return _implementation(); } @@ -98,7 +97,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @param _newVersion representing the version name of the new implementation to be set. * @param _newImplementation representing the address of the new implementation to be set. */ - function upgradeTo(string _newVersion, address _newImplementation) external ifOwner { + function upgradeTo(string calldata _newVersion, address _newImplementation) external ifOwner { _upgradeTo(_newVersion, _newImplementation); } @@ -110,10 +109,12 @@ 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) external payable ifOwner { + function upgradeToAndCall(string calldata _newVersion, address _newImplementation, bytes calldata _data) external payable ifOwner { _upgradeTo(_newVersion, _newImplementation); + bool success; /*solium-disable-next-line security/no-call-value*/ - require(address(this).call.value(msg.value)(_data), "Fail in executing the function of implementation contract"); + (success, ) = address(this).call.value(msg.value)(_data); + require(success, "Fail in executing the function of implementation contract"); } } diff --git a/contracts/proxy/PercentageTransferManagerProxy.sol b/contracts/proxy/PercentageTransferManagerProxy.sol index c5c93560f..6c85d0f5f 100644 --- a/contracts/proxy/PercentageTransferManagerProxy.sol +++ b/contracts/proxy/PercentageTransferManagerProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/TransferManager/PercentageTransferManagerStorage.sol"; import "./OwnedProxy.sol"; diff --git a/contracts/proxy/PreSaleSTOProxy.sol b/contracts/proxy/PreSaleSTOProxy.sol index 895cf3fdf..2753ec3b9 100644 --- a/contracts/proxy/PreSaleSTOProxy.sol +++ b/contracts/proxy/PreSaleSTOProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; diff --git a/contracts/proxy/Proxy.sol b/contracts/proxy/Proxy.sol index 6cfbce44f..ac9d471ca 100644 --- a/contracts/proxy/Proxy.sol +++ b/contracts/proxy/Proxy.sol @@ -1,16 +1,15 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; /** * @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); + function _implementation() internal view returns(address); /** * @dev Fallback function. @@ -31,14 +30,11 @@ contract Proxy { // 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) } @@ -46,7 +42,7 @@ contract Proxy { } } - function () public payable { + function() external payable { _fallback(); } -} \ No newline at end of file +} diff --git a/contracts/proxy/SecurityTokenRegistryProxy.sol b/contracts/proxy/SecurityTokenRegistryProxy.sol index 6acc6e38f..906797985 100644 --- a/contracts/proxy/SecurityTokenRegistryProxy.sol +++ b/contracts/proxy/SecurityTokenRegistryProxy.sol @@ -1,9 +1,8 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../storage/EternalStorage.sol"; import "./OwnedUpgradeabilityProxy.sol"; - /** * @title SecurityTokenRegistryProxy * @dev This proxy holds the storage of the SecurityTokenRegistry contract and delegates every call to the current implementation set. @@ -13,4 +12,4 @@ import "./OwnedUpgradeabilityProxy.sol"; /*solium-disable-next-line no-empty-blocks*/ contract SecurityTokenRegistryProxy is EternalStorage, OwnedUpgradeabilityProxy { -} \ No newline at end of file +} diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol index 6df4c8cf4..290cea83d 100644 --- a/contracts/proxy/USDTieredSTOProxy.sol +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "../modules/STO/USDTieredSTOStorage.sol"; import "./OwnedProxy.sol"; @@ -11,21 +11,14 @@ import "../modules/ModuleStorage.sol"; * @title USDTiered STO module Proxy */ contract USDTieredSTOProxy is USDTieredSTOStorage, STOStorage, 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" - ); + 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/UpgradeabilityProxy.sol b/contracts/proxy/UpgradeabilityProxy.sol index 37b64af3e..dc702dae9 100644 --- a/contracts/proxy/UpgradeabilityProxy.sol +++ b/contracts/proxy/UpgradeabilityProxy.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./Proxy.sol"; import "openzeppelin-solidity/contracts/utils/Address.sol"; @@ -8,7 +8,6 @@ import "openzeppelin-solidity/contracts/utils/Address.sol"; * @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded */ contract UpgradeabilityProxy is Proxy { - // Version name of the current implementation string internal __version; @@ -27,7 +26,7 @@ contract UpgradeabilityProxy is Proxy { * @param _newVersion representing the version name of the new implementation to be set * @param _newImplementation representing the address of the new implementation to be set */ - function _upgradeTo(string _newVersion, address _newImplementation) internal { + function _upgradeTo(string memory _newVersion, address _newImplementation) internal { require( __implementation != _newImplementation && _newImplementation != address(0), "Old address is not allowed and implementation address should not be 0x" @@ -40,4 +39,4 @@ contract UpgradeabilityProxy is Proxy { emit Upgraded(_newVersion, _newImplementation); } -} \ No newline at end of file +} diff --git a/contracts/storage/EternalStorage.sol b/contracts/storage/EternalStorage.sol index 637b5f2f3..114f0125c 100644 --- a/contracts/storage/EternalStorage.sol +++ b/contracts/storage/EternalStorage.sol @@ -1,7 +1,6 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; contract EternalStorage { - /// @notice Internal mappings used to store all kinds on data into the contract mapping(bytes32 => uint256) internal uintStorage; mapping(bytes32 => string) internal stringStorage; @@ -53,7 +52,7 @@ contract EternalStorage { bytes32Storage[_key] = _value; } - function set(bytes32 _key, string _value) internal { + function set(bytes32 _key, string memory _value) internal { stringStorage[_key] = _value; } @@ -69,27 +68,26 @@ contract EternalStorage { /// {uint256 date, string name, address owner} etc. /// string _name = getString(keccak256(abi.encodePacked("registeredSymbols_name", "TOKEN")); - function getBool(bytes32 _key) internal view returns (bool) { + function getBool(bytes32 _key) internal view returns(bool) { return boolStorage[_key]; } - function getUint(bytes32 _key) internal view returns (uint256) { + function getUint(bytes32 _key) internal view returns(uint256) { return uintStorage[_key]; } - function getAddress(bytes32 _key) internal view returns (address) { + function getAddress(bytes32 _key) internal view returns(address) { return addressStorage[_key]; } - function getString(bytes32 _key) internal view returns (string) { + function getString(bytes32 _key) internal view returns(string memory) { return stringStorage[_key]; } - function getBytes32(bytes32 _key) internal view returns (bytes32) { + function getBytes32(bytes32 _key) internal view returns(bytes32) { return bytes32Storage[_key]; } - //////////////////////////// // deleteArray functions //////////////////////////// @@ -99,7 +97,6 @@ contract EternalStorage { /// in this case we have the helper function deleteArrayBytes32() which will do it for us /// deleteArrayBytes32(keccak256(abi.encodePacked("tokensOwnedByOwner", 0x1), 3); -- it will delete the index 3 - //Deletes from mapping (bytes32 => array[]) at index _index function deleteArrayAddress(bytes32 _key, uint256 _index) internal { address[] storage array = addressArrayStorage[_key]; @@ -151,7 +148,7 @@ contract EternalStorage { bytes32ArrayStorage[_key].push(_value); } - function pushArray(bytes32 _key, string _value) internal { + function pushArray(bytes32 _key, string memory _value) internal { stringArrayStorage[_key].push(_value); } @@ -165,21 +162,21 @@ contract EternalStorage { /// @notice used to intialize the array /// Ex1- mapping (address => address[]) public reputation; /// reputation[0x1] = new address[](0); It can be replaced as - /// setArray(hash('reputation', 0x1), new address[](0)); - - function setArray(bytes32 _key, address[] _value) internal { + /// setArray(hash('reputation', 0x1), new address[](0)); + + function setArray(bytes32 _key, address[] memory _value) internal { addressArrayStorage[_key] = _value; } - function setArray(bytes32 _key, uint256[] _value) internal { + function setArray(bytes32 _key, uint256[] memory _value) internal { uintArrayStorage[_key] = _value; } - function setArray(bytes32 _key, bytes32[] _value) internal { + function setArray(bytes32 _key, bytes32[] memory _value) internal { bytes32ArrayStorage[_key] = _value; } - function setArray(bytes32 _key, string[] _value) internal { + function setArray(bytes32 _key, string[] memory _value) internal { stringArrayStorage[_key] = _value; } @@ -192,19 +189,19 @@ 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) internal view returns(address[] memory) { return addressArrayStorage[_key]; } - function getArrayBytes32(bytes32 _key) internal view returns(bytes32[]) { + function getArrayBytes32(bytes32 _key) internal view returns(bytes32[] memory) { return bytes32ArrayStorage[_key]; } - function getArrayString(bytes32 _key) internal view returns(string[]) { + function getArrayString(bytes32 _key) internal view returns(string[] memory) { return stringArrayStorage[_key]; } - function getArrayUint(bytes32 _key) internal view returns(uint[]) { + function getArrayUint(bytes32 _key) internal view returns(uint[] memory) { return uintArrayStorage[_key]; } @@ -213,8 +210,8 @@ contract EternalStorage { /////////////////////////////////// /// @notice set the value of particular index of the address array /// Ex1- mapping(bytes32 => address[]) moduleList; - /// general way is -- moduleList[moduleType][index] = temp; - /// It can be re-write as -- setArrayIndexValue(keccak256(abi.encodePacked('moduleList', moduleType)), index, temp); + /// general way is -- moduleList[moduleType][index] = temp; + /// It can be re-write as -- setArrayIndexValue(keccak256(abi.encodePacked('moduleList', moduleType)), index, temp); function setArrayIndexValue(bytes32 _key, uint256 _index, address _value) internal { addressArrayStorage[_key][_index] = _value; @@ -228,13 +225,13 @@ contract EternalStorage { bytes32ArrayStorage[_key][_index] = _value; } - function setArrayIndexValue(bytes32 _key, uint256 _index, string _value) internal { + function setArrayIndexValue(bytes32 _key, uint256 _index, string memory _value) internal { stringArrayStorage[_key][_index] = _value; } - ///////////////////////////// - /// Public getters functions - ///////////////////////////// + ///////////////////////////// + /// Public getters functions + ///////////////////////////// function getUintValues(bytes32 _variable) public view returns(uint256) { return uintStorage[_variable]; @@ -244,7 +241,7 @@ contract EternalStorage { return boolStorage[_variable]; } - function getStringValues(bytes32 _variable) public view returns(string) { + function getStringValues(bytes32 _variable) public view returns(string memory) { return stringStorage[_variable]; } @@ -256,7 +253,7 @@ contract EternalStorage { return bytes32Storage[_variable]; } - function getBytesValues(bytes32 _variable) public view returns(bytes) { + function getBytesValues(bytes32 _variable) public view returns(bytes memory) { return bytesStorage[_variable]; } diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index 85153e816..702d118f8 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "./SecurityToken.sol"; import "../interfaces/ISTFactory.sol"; @@ -7,10 +7,9 @@ import "../interfaces/ISTFactory.sol"; * @title Proxy for deploying SecurityToken instances */ contract STFactory is ISTFactory { - address public transferManagerFactory; - constructor (address _transferManagerFactory) public { + constructor(address _transferManagerFactory) public { transferManagerFactory = _transferManagerFactory; } @@ -19,24 +18,27 @@ contract STFactory is ISTFactory { * Future versions of the proxy can attach different modules or pass different parameters. */ function deployToken( - string _name, - string _symbol, + string calldata _name, + string calldata _symbol, uint8 _decimals, - string _tokenDetails, + string calldata _tokenDetails, address _issuer, bool _divisible, address _polymathRegistry - ) external returns (address) { - address newSecurityTokenAddress = new SecurityToken( + ) + external + returns(address) + { + SecurityToken newSecurityToken = new SecurityToken( _name, _symbol, _decimals, - _divisible ? 1 : uint256(10)**_decimals, + _divisible ? 1 : uint256(10) ** _decimals, _tokenDetails, _polymathRegistry ); - SecurityToken(newSecurityTokenAddress).addModule(transferManagerFactory, "", 0, 0); - SecurityToken(newSecurityTokenAddress).transferOwnership(_issuer); - return newSecurityTokenAddress; + newSecurityToken.addModule(transferManagerFactory, "", 0, 0); + newSecurityToken.transferOwnership(_issuer); + return address(newSecurityToken); } } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index f3ecbdaa3..2979a6a5d 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/Math.sol"; import "../interfaces/IPoly.sol"; @@ -65,16 +65,16 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address public controller; // Records added modules - module list should be order agnostic! - mapping (uint8 => address[]) modules; + mapping(uint8 => address[]) modules; // Records information about the module - mapping (address => TokenLib.ModuleData) modulesToData; + mapping(address => TokenLib.ModuleData) modulesToData; // Records added module names - module list should be order agnostic! - mapping (bytes32 => address[]) names; + mapping(bytes32 => address[]) names; // Map each investor to a series of checkpoints - mapping (address => TokenLib.Checkpoint[]) checkpointBalances; + mapping(address => TokenLib.Checkpoint[]) checkpointBalances; // List of checkpoints that relate to total supply TokenLib.Checkpoint[] checkpointTotalSupply; @@ -126,16 +126,10 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater bool _verifyTransfer, bytes _data ); - event ForceBurn( - address indexed _controller, - address indexed _from, - 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) { + function _isModule(address _module, uint8 _type) internal view returns(bool) { require(modulesToData[_module].module == _module, "Wrong address"); require(!modulesToData[_module].isArchived, "Module archived"); for (uint256 i = 0; i < modulesToData[_module].moduleTypes.length; i++) { @@ -172,7 +166,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater _; } - modifier isEnabled(string _nameKey) { + modifier isEnabled(string memory _nameKey) { require(IFeatureRegistry(featureRegistry).getFeatureStatus(_nameKey)); _; } @@ -195,23 +189,22 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _tokenDetails Details of the token that are stored off-chain * @param _polymathRegistry Contract address of the polymath registry */ - constructor ( - string _name, - string _symbol, + constructor( + string memory _name, + string memory _symbol, uint8 _decimals, uint256 _granularity, - string _tokenDetails, + string memory _tokenDetails, address _polymathRegistry - ) - public - ERC20Detailed(_name, _symbol, _decimals) - RegistryUpdater(_polymathRegistry) + ) + public + ERC20Detailed(_name, _symbol, _decimals) RegistryUpdater(_polymathRegistry) { //When it is created, the owner is the STR updateFromRegistry(); tokenDetails = _tokenDetails; granularity = _granularity; - securityTokenVersion = SemanticVersion(2,0,0); + securityTokenVersion = SemanticVersion(2, 0, 0); } /** @@ -226,11 +219,14 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function addModuleWithLabel( address _moduleFactory, - bytes _data, + bytes memory _data, uint256 _maxCost, - uint256 _budget, + uint256 _budget, bytes32 _label - ) public onlyOwner nonReentrant { + ) + public + onlyOwner nonReentrant + { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); @@ -253,7 +249,14 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater modules[moduleTypes[i]].push(module); } modulesToData[module] = TokenLib.ModuleData( - moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length, _label + moduleName, + module, + _moduleFactory, + false, + moduleTypes, + moduleIndexes, + names[moduleName].length, + _label ); names[moduleName].push(module); //Emit log event @@ -264,12 +267,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /** * @notice addModule function will call addModuleWithLabel() with an empty label for backward compatible */ - function addModule( - address _moduleFactory, - bytes _data, - uint256 _maxCost, - uint256 _budget - ) external { + function addModule(address _moduleFactory, bytes calldata _data, uint256 _maxCost, uint256 _budget) external { addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, ""); } @@ -294,46 +292,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _module address of module to unarchive */ function removeModule(address _module) external onlyOwner { - 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; - for (uint256 i = 0; i < moduleTypes.length; i++) { - _removeModuleWithIndex(moduleTypes[i], modulesToData[_module].moduleIndexes[i]); - /* modulesToData[_module].moduleType[moduleTypes[i]] = false; */ - } - // Remove from module names list - uint256 index = modulesToData[_module].nameIndex; - bytes32 name = modulesToData[_module].name; - uint256 length = names[name].length; - names[name][index] = names[name][length - 1]; - names[name].length = length - 1; - if ((length - 1) != index) { - modulesToData[names[name][index]].nameIndex = index; - } - // Remove from modulesToData - delete modulesToData[_module]; - } - - /** - * @notice Internal - Removes a module attached to the SecurityToken by index - */ - function _removeModuleWithIndex(uint8 _type, uint256 _index) internal { - uint256 length = modules[_type].length; - modules[_type][_index] = modules[_type][length - 1]; - modules[_type].length = length - 1; - - if ((length - 1) != _index) { - //Need to find index of _type in moduleTypes of module we are moving - uint8[] memory newTypes = modulesToData[modules[_type][_index]].moduleTypes; - for (uint256 i = 0; i < newTypes.length; i++) { - if (newTypes[i] == _type) { - modulesToData[modules[_type][_index]].moduleIndexes[i] = _index; - } - } - } + TokenLib.removeModule(_module, modules, modulesToData, names); } /** @@ -346,13 +305,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return uint8 array of module types * @return bytes32 module label */ - function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[], bytes32) { - return (modulesToData[_module].name, - modulesToData[_module].module, - modulesToData[_module].moduleFactory, - modulesToData[_module].isArchived, - modulesToData[_module].moduleTypes, - modulesToData[_module].label); + function getModule(address _module) external view returns(bytes32, address, address, bool, uint8[] memory, bytes32) { + return (modulesToData[_module].name, modulesToData[_module].module, modulesToData[_module].moduleFactory, modulesToData[_module].isArchived, modulesToData[_module].moduleTypes, modulesToData[_module].label); } /** @@ -360,7 +314,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _name name of the module * @return address[] list of modules with this name */ - function getModulesByName(bytes32 _name) external view returns (address[]) { + function getModulesByName(bytes32 _name) external view returns(address[] memory) { return names[_name]; } @@ -369,11 +323,11 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _type type of the module * @return address[] list of modules with this type */ - function getModulesByType(uint8 _type) external view returns (address[]) { + function getModulesByType(uint8 _type) external view returns(address[] memory) { return modules[_type]; } - /** + /** * @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 @@ -392,24 +346,14 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _increase true if budget has to be increased, false if decrease */ function changeModuleBudget(address _module, uint256 _change, bool _increase) external onlyOwner { - require(modulesToData[_module].module != address(0), "Module missing"); - uint256 currentAllowance = IPoly(polyToken).allowance(address(this), _module); - uint256 newAllowance; - if (_increase) { - require(IPoly(polyToken).increaseApproval(_module, _change), "IncreaseApproval fail"); - newAllowance = currentAllowance.add(_change); - } else { - require(IPoly(polyToken).decreaseApproval(_module, _change), "Insufficient allowance"); - newAllowance = currentAllowance.sub(_change); - } - emit ModuleBudgetChanged(modulesToData[_module].moduleTypes, _module, currentAllowance, newAllowance); + TokenLib.changeModuleBudget(_module, _change, _increase, polyToken, modulesToData); } /** * @notice updates the tokenDetails associated with the token * @param _newTokenDetails New token details */ - function updateTokenDetails(string _newTokenDetails) external onlyOwner { + function updateTokenDetails(string calldata _newTokenDetails) external onlyOwner { emit UpdateTokenDetails(tokenDetails, _newTokenDetails); tokenDetails = _newTokenDetails; } @@ -439,7 +383,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * 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[]) { + function getInvestors() external view returns(address[] memory) { return investorData.investors; } @@ -449,7 +393,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _checkpointId Checkpoint id at which investor list is to be populated * @return list of investors */ - function getInvestorsAt(uint256 _checkpointId) external view returns(address[]) { + function getInvestorsAt(uint256 _checkpointId) external view returns(address[] memory) { uint256 count = 0; uint256 i; for (i = 0; i < investorData.investors.length; i++) { @@ -475,7 +419,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _end Position of investor to stop iteration at * @return list of investors */ - function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]) { + function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[] memory) { require(_end <= investorData.investors.length, "Invalid end"); address[] memory investors = new address[](_end.sub(_start)); uint256 index = 0; @@ -535,7 +479,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _value value of transfer * @return bool success */ - function transfer(address _to, uint256 _value) public returns (bool success) { + function transfer(address _to, uint256 _value) public returns(bool success) { return transferWithData(_to, _value, ""); } @@ -546,7 +490,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _data data to indicate validation * @return bool success */ - function transferWithData(address _to, uint256 _value, bytes _data) public returns (bool success) { + function transferWithData(address _to, uint256 _value, bytes memory _data) public returns(bool success) { require(_updateTransfer(msg.sender, _to, _value, _data), "Transfer invalid"); require(super.transfer(_to, _value)); return true; @@ -571,7 +515,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _data data to indicate validation * @return bool success */ - function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) public returns(bool) { + function transferFromWithData(address _from, address _to, uint256 _value, bytes memory _data) public returns(bool) { require(_updateTransfer(_from, _to, _value, _data), "Transfer invalid"); require(super.transferFrom(_from, _to, _value)); return true; @@ -585,7 +529,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _data data to indicate validation * @return bool success */ - function _updateTransfer(address _from, address _to, uint256 _value, bytes _data) internal nonReentrant returns(bool) { + function _updateTransfer(address _from, address _to, uint256 _value, bytes memory _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. @@ -618,9 +562,13 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address _from, address _to, uint256 _value, - bytes _data, + bytes memory _data, bool _isTransfer - ) internal checkGranularity(_value) returns (bool) { + ) + internal + checkGranularity(_value) + returns(bool) + { if (!transfersFrozen) { bool isInvalid = false; bool isValid = false; @@ -656,7 +604,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _data data to indicate validation * @return bool */ - function verifyTransfer(address _from, address _to, uint256 _value, bytes _data) public returns (bool) { + function verifyTransfer(address _from, address _to, uint256 _value, bytes memory _data) public returns(bool) { return _verifyTransfer(_from, _to, _value, _data, false); } @@ -664,7 +612,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @notice Permanently freeze minting of this security token. * @dev It MUST NOT be possible to increase `totalSuppy` after this function is called. */ - function freezeMinting() external isMintingAllowed() isEnabled("freezeMintingAllowed") onlyOwner { + function freezeMinting() external isMintingAllowed isEnabled("freezeMintingAllowed") onlyOwner { mintingFrozen = true; /*solium-disable-next-line security/no-block-members*/ emit FreezeMinting(now); @@ -677,7 +625,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _value Number of tokens be minted * @return success */ - function mint(address _investor, uint256 _value) public returns (bool success) { + function mint(address _investor, uint256 _value) public returns(bool success) { return mintWithData(_investor, _value, ""); } @@ -692,8 +640,13 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater function mintWithData( address _investor, uint256 _value, - bytes _data - ) public onlyModuleOrOwner(MINT_KEY) isMintingAllowed() returns (bool success) { + bytes memory _data + ) + public + onlyModuleOrOwner(MINT_KEY) + isMintingAllowed + returns(bool success) + { require(_updateTransfer(address(0), _investor, _value, _data), "Transfer invalid"); _adjustTotalSupplyCheckpoints(); _mint(_investor, _value); @@ -708,7 +661,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @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 returns (bool success) { + function mintMulti(address[] calldata _investors, uint256[] calldata _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]); @@ -727,13 +680,17 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) { for (uint256 i = 0; i < modules[PERMISSION_KEY].length; i++) { - if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived) - return TokenLib.checkPermission(modules[PERMISSION_KEY], _delegate, _module, _perm); + if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived) return TokenLib.checkPermission( + modules[PERMISSION_KEY], + _delegate, + _module, + _perm + ); } return false; } - function _checkAndBurn(address _from, uint256 _value, bytes _data) internal returns(bool) { + function _checkAndBurn(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); _adjustTotalSupplyCheckpoints(); _burn(_from, _value); @@ -746,11 +703,11 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _value No. of tokens that get burned * @param _data data to indicate validation */ - function burnWithData(uint256 _value, bytes _data) public onlyModule(BURN_KEY) { + function burnWithData(uint256 _value, bytes memory _data) public onlyModule(BURN_KEY) { require(_checkAndBurn(msg.sender, _value, _data), "Burn invalid"); } - function _checkAndBurnFrom(address _from, uint256 _value, bytes _data) internal returns(bool) { + function _checkAndBurnFrom(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); _adjustTotalSupplyCheckpoints(); _burnFrom(_from, _value); @@ -764,7 +721,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _value No. of tokens that get burned * @param _data data to indicate validation */ - function burnFromWithData(address _from, uint256 _value, bytes _data) public onlyModule(BURN_KEY) { + function burnFromWithData(address _from, uint256 _value, bytes memory _data) public onlyModule(BURN_KEY) { require(_checkAndBurnFrom(_from, _value, _data), "Burn invalid"); } @@ -773,7 +730,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return uint256 */ function createCheckpoint() external onlyModuleOrOwner(CHECKPOINT_KEY) returns(uint256) { - require(currentCheckpointId < 2**256 - 1); + require(currentCheckpointId < 2 ** 256 - 1); currentCheckpointId = currentCheckpointId + 1; /*solium-disable-next-line security/no-block-members*/ checkpointTimes.push(now); @@ -786,7 +743,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @notice Gets list of times that checkpoints were created * @return List of checkpoint times */ - function getCheckpointTimes() external view returns(uint256[]) { + function getCheckpointTimes() external view returns(uint256[] memory) { return checkpointTimes; } @@ -840,7 +797,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @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) public onlyController { + function forceTransfer(address _from, address _to, uint256 _value, bytes memory _data, bytes memory _log) public onlyController { bool verified = _updateTransfer(_from, _to, _value, _data); _transfer(_from, _to, _value); emit ForceTransfer(msg.sender, _from, _to, _value, verified, _log); @@ -853,7 +810,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @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) public onlyController { + function forceBurn(address _from, uint256 _value, bytes memory _data, bytes memory _log) public onlyController { bool verified = _checkAndBurn(_from, _value, _data); emit ForceBurn(msg.sender, _from, _value, verified, _log); } @@ -861,7 +818,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /** * @notice Returns the version of the SecurityToken */ - function getVersion() external view returns(uint8[]) { + function getVersion() external view returns(uint8[] memory) { uint8[] memory _version = new uint8[](3); _version[0] = securityTokenVersion.major; _version[1] = securityTokenVersion.minor; diff --git a/migrations/1_deploy_token.js b/migrations/1_deploy_token.js index 47f0e97a9..a31ddc4a7 100644 --- a/migrations/1_deploy_token.js +++ b/migrations/1_deploy_token.js @@ -1,9 +1,8 @@ -const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') -const Web3 = require('web3') -web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) +const DevPolyToken = artifacts.require("./helpers/PolyTokenFaucet.sol"); +const Web3 = require("web3"); +web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); -module.exports = function (deployer, network, accounts) { - const PolymathAccount = accounts[0] - return deployer.deploy(DevPolyToken, {from: PolymathAccount}).then(() => {}) - -} \ No newline at end of file +module.exports = function(deployer, network, accounts) { + const PolymathAccount = accounts[0]; + return deployer.deploy(DevPolyToken, { from: PolymathAccount }).then(() => {}); +}; diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index ca24170c5..9618425c3 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,345 +1,465 @@ -const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') -const GeneralTransferManagerLogic = artifacts.require('./GeneralTransferManager.sol') -const GeneralPermissionManagerLogic = artifacts.require('./GeneralPermissionManager.sol') -const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') -const PercentageTransferManagerLogic = artifacts.require('./PercentageTransferManager.sol') -const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') -const USDTieredSTOLogic = artifacts.require('./USDTieredSTO.sol'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') -const CountTransferManagerLogic = artifacts.require('./CountTransferManager.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'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol') -const ManualApprovalTransferManagerLogic = artifacts.require('./ManualApprovalTransferManager.sol') -const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol') +const PolymathRegistry = artifacts.require("./PolymathRegistry.sol"); +const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); +const GeneralPermissionManagerLogic = artifacts.require("./GeneralPermissionManager.sol"); +const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); +const PercentageTransferManagerLogic = artifacts.require("./PercentageTransferManager.sol"); +const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); +const USDTieredSTOLogic = artifacts.require("./USDTieredSTO.sol"); +const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); +const CountTransferManagerLogic = artifacts.require("./CountTransferManager.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"); +const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); +const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); +const ManualApprovalTransferManagerLogic = artifacts.require("./ManualApprovalTransferManager.sol"); +const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const CappedSTOLogic = artifacts.require("./CappedSTO.sol"); -const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol') -const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol') -const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol') -const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') -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 SecurityToken = artifacts.require('./tokens/SecurityToken.sol') +const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); +const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); +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 SecurityToken = artifacts.require("./tokens/SecurityToken.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); -let BigNumber = require('bignumber.js'); -const cappedSTOSetupCost = new BigNumber(20000).times(new BigNumber(10).pow(18)); // 20K POLY fee -const usdTieredSTOSetupCost = new BigNumber(100000).times(new BigNumber(10).pow(18)); // 100K POLY fee -const initRegFee = new BigNumber(250).times(new BigNumber(10).pow(18)); // 250 POLY fee for registering ticker or security token in registry + +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const nullAddress = "0x0000000000000000000000000000000000000000"; +const cappedSTOSetupCost = new BN(20000).mul(new BN(10).pow(new BN(18))); // 20K POLY fee +const usdTieredSTOSetupCost = new BN(100000).mul(new BN(10).pow(new BN(18))); // 100K POLY fee +const initRegFee = new BN(250).mul(new BN(10).pow(new BN(18))); // 250 POLY fee for registering ticker or security token in registry let PolyToken; let UsdToken; let ETHOracle; let POLYOracle; -const Web3 = require('web3') - -module.exports = function (deployer, network, accounts) { - // Ethereum account address hold by the Polymath (Act as the main account which have ownable permissions) - let PolymathAccount; - let moduleRegistry; - let polymathRegistry; - let web3 - if (network === 'development') { - web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) - PolymathAccount = accounts[0] - PolyToken = DevPolyToken.address // Development network polytoken address - deployer.deploy(DevPolyToken, {from: PolymathAccount}).then(() => { - DevPolyToken.deployed().then((mockedUSDToken) => { - UsdToken = mockedUSDToken.address; - }); - }); - deployer.deploy(MockOracle, PolyToken, "POLY", "USD", new BigNumber(0.5).times(new BigNumber(10).pow(18)), {from: PolymathAccount}).then(() => { - MockOracle.deployed().then((mockedOracle) => { - POLYOracle = mockedOracle.address; - }); - }); - deployer.deploy(MockOracle, 0, "ETH", "USD", new BigNumber(500).times(new BigNumber(10).pow(18)), {from: PolymathAccount}).then(() => { - MockOracle.deployed().then((mockedOracle) => { - ETHOracle = mockedOracle.address; - }); - }); - - } else if (network === 'kovan') { - web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/g5xfoQ0jFSE9S5LwM1Ei')) - PolymathAccount = accounts[0] - PolyToken = '0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792' // PolyToken Kovan Faucet Address - POLYOracle = '0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C' // Poly Oracle Kovan Address - ETHOracle = '0xCE5551FC9d43E9D2CC255139169FC889352405C8' // ETH Oracle Kovan Address - } else if (network === 'mainnet') { - web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/g5xfoQ0jFSE9S5LwM1Ei')) - PolymathAccount = accounts[0] - PolyToken = '0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC' // Mainnet PolyToken Address - POLYOracle = '0x52cb4616E191Ff664B0bff247469ce7b74579D1B' // Poly Oracle Mainnet Address - ETHOracle = '0x60055e9a93aae267da5a052e95846fa9469c0e7a' // ETH Oracle Mainnet Address - } if (network === 'coverage') { - web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) - PolymathAccount = accounts[0] - PolyToken = DevPolyToken.address // Development network polytoken address - deployer.deploy(MockOracle, PolyToken, "POLY", "USD", new BigNumber(0.5).times(new BigNumber(10).pow(18)), {from: PolymathAccount}).then(() => { - MockOracle.deployed().then((mockedOracle) => { - POLYOracle = mockedOracle.address; - }); - }); - deployer.deploy(MockOracle, 0, "ETH", "USD", new BigNumber(500).times(new BigNumber(10).pow(18)), {from: PolymathAccount}).then(() => { - MockOracle.deployed().then((mockedOracle) => { - ETHOracle = mockedOracle.address; - }); - }); - } +module.exports = function(deployer, network, accounts) { + // Ethereum account address hold by the Polymath (Act as the main account which have ownable permissions) + let PolymathAccount; + let moduleRegistry; + let polymathRegistry; + let web3; + if (network === "development") { + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + PolymathAccount = accounts[0]; + PolyToken = DevPolyToken.address; // Development network polytoken address + deployer.deploy(DevPolyToken, { from: PolymathAccount }).then(() => { + DevPolyToken.deployed().then(mockedUSDToken => { + UsdToken = mockedUSDToken.address; + }); + }); + deployer + .deploy( + MockOracle, + PolyToken, + web3.utils.fromAscii("POLY"), + web3.utils.fromAscii("USD"), + new BN(5).mul(new BN(10).pow(new BN(17))), + { from: PolymathAccount } + ) + .then(() => { + MockOracle.deployed().then(mockedOracle => { + POLYOracle = mockedOracle.address; + }); + }); + deployer + .deploy( + MockOracle, + nullAddress, + web3.utils.fromAscii("ETH"), + web3.utils.fromAscii("USD"), + new BN(500).mul(new BN(10).pow(new BN(18))), + { from: PolymathAccount } + ) + .then(() => { + MockOracle.deployed().then(mockedOracle => { + ETHOracle = mockedOracle.address; + }); + }); + } else if (network === "kovan") { + web3 = new Web3(new Web3.providers.HttpProvider("https://kovan.infura.io/g5xfoQ0jFSE9S5LwM1Ei")); + PolymathAccount = accounts[0]; + PolyToken = "0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792"; // PolyToken Kovan Faucet Address + POLYOracle = "0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C"; // Poly Oracle Kovan Address + ETHOracle = "0xCE5551FC9d43E9D2CC255139169FC889352405C8"; // ETH Oracle Kovan Address + } else if (network === "mainnet") { + web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/g5xfoQ0jFSE9S5LwM1Ei")); + PolymathAccount = accounts[0]; + PolyToken = "0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC"; // Mainnet PolyToken Address + POLYOracle = "0x52cb4616E191Ff664B0bff247469ce7b74579D1B"; // Poly Oracle Mainnet Address + ETHOracle = "0x60055e9a93aae267da5a052e95846fa9469c0e7a"; // ETH Oracle Mainnet Address + } + if (network === "coverage") { + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + PolymathAccount = accounts[0]; + PolyToken = DevPolyToken.address; // Development network polytoken address + deployer + .deploy(MockOracle, PolyToken, web3.utils.fromAscii("POLY"), web3.utils.fromAscii("USD"), new BN(0.5).mul(new BN(10).pow(new BN(18))), { from: PolymathAccount }) + .then(() => { + MockOracle.deployed().then(mockedOracle => { + POLYOracle = mockedOracle.address; + }); + }); + deployer.deploy(MockOracle, nullAddress, web3.utils.fromAscii("ETH"), web3.utils.fromAscii("USD"), new BN(500).mul(new BN(10).pow(new BN(18))), { from: PolymathAccount }).then(() => { + MockOracle.deployed().then(mockedOracle => { + ETHOracle = mockedOracle.address; + }); + }); + } - const functionSignatureProxy = { - name: 'initialize', - type: 'function', - inputs: [{ - type:'address', - name: '_polymathRegistry' - },{ - type: 'address', - name: '_STFactory' - },{ - type: 'uint256', - name: '_stLaunchFee' - },{ - type: 'uint256', - name: '_tickerRegFee' - },{ - type: 'address', - name: '_owner' - },{ - type: 'address', - name: '_getterContract' - }] - }; + const functionSignatureProxy = { + name: "initialize", + type: "function", + inputs: [ + { + type: "address", + name: "_polymathRegistry" + }, + { + type: "address", + name: "_STFactory" + }, + { + type: "uint256", + name: "_stLaunchFee" + }, + { + type: "uint256", + name: "_tickerRegFee" + }, + { + type: "address", + name: "_owner" + }, + { + type: 'address', + name: '_getterContract' + } + ] + }; - const functionSignatureProxyMR = { - name: 'initialize', - type: 'function', - inputs: [{ - type:'address', - name: '_polymathRegistry' - },{ - type: 'address', - name: '_owner' - }] - }; + const functionSignatureProxyMR = { + name: "initialize", + type: "function", + inputs: [ + { + type: "address", + name: "_polymathRegistry" + }, + { + type: "address", + name: "_owner" + } + ] + }; - // POLYMATH NETWORK Configuration :: DO THIS ONLY ONCE - // A) Deploy the PolymathRegistry contract - return deployer.deploy(PolymathRegistry, {from: PolymathAccount}).then(() => { - return PolymathRegistry.deployed(); - }).then((_polymathRegistry) => { - polymathRegistry = _polymathRegistry; - return polymathRegistry.changeAddress("PolyToken", PolyToken, {from: PolymathAccount}); - }).then(() => { - // Deploy libraries - return deployer.deploy(TokenLib, {from: PolymathAccount}); - }).then(() => { - // Link libraries - deployer.link(TokenLib, SecurityToken); - deployer.link(TokenLib, STFactory); - // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) - return deployer.deploy(ModuleRegistry, {from: PolymathAccount}); - }).then(() => { - return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); - }).then(() => { - let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [polymathRegistry.address, PolymathAccount]); - return ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, {from: PolymathAccount}); - }).then(() => { - 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 GeneralPermissionManagerLogic Contract (Factory used to generate the GeneralPermissionManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralPermissionManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); - }).then(() => { - // B) Deploy the CountTransferManagerLogic Contract (Factory used to generate the CountTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(CountTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); - }).then(() => { - // B) Deploy the ManualApprovalTransferManagerLogic Contract (Factory used to generate the ManualApprovalTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(ManualApprovalTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); - }).then(() => { - // B) Deploy the PercentageTransferManagerLogic Contract (Factory used to generate the PercentageTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(PercentageTransferManagerLogic, "0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", {from: PolymathAccount}); - }).then(() => { - // 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 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 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 CappedSTOLogic Contract (Factory used to generate the CappedSTO contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(CappedSTOLogic, "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, 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) - return deployer.deploy(GeneralPermissionManagerFactory, 0, 0, 0, GeneralPermissionManagerLogic.address, {from: PolymathAccount}); - }).then(() => { - // 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, 0, 0, 0, CountTransferManagerLogic.address, {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) - return deployer.deploy(PercentageTransferManagerFactory, 0, 0, 0, PercentageTransferManagerLogic.address, {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) - return deployer.deploy(EtherDividendCheckpointFactory, 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, 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) - return deployer.deploy(ManualApprovalTransferManagerFactory, 0, 0, 0, ManualApprovalTransferManagerLogic.address, {from: PolymathAccount}); - }).then(() => { - // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. - return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // K) Deploy the FeatureRegistry contract to control feature switches - return deployer.deploy(FeatureRegistry, PolymathRegistry.address, {from: PolymathAccount}); - }).then(() => { - // Assign the address into the FeatureRegistry key - return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, {from: PolymathAccount}); - }).then(() => { - // J) Deploy the SecurityTokenRegistry contract (Used to hold the deployed secuirtyToken details. It also act as the interface to deploy the SecurityToken) - return deployer.deploy(SecurityTokenRegistry, {from: PolymathAccount}) - }).then(()=> { - return deployer.deploy(SecurityTokenRegistryProxy, {from: PolymathAccount}); - }).then(() => { - return deployer.deploy(STRGetter, {from: PolymathAccount}); - }).then(() => { - let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolymathAccount, STRGetter.address]); - return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); - }).then(() => { - // Assign the address into the SecurityTokenRegistry key - return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); - }).then(() => { - // Update all addresses into the registry contract by calling the function updateFromregistry - return moduleRegistry.updateFromRegistry({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. - return moduleRegistry.registerModule(PercentageTransferManagerFactory.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. - return moduleRegistry.registerModule(CountTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // 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(() => { - // 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(GeneralPermissionManagerFactory.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. - return moduleRegistry.registerModule(EtherDividendCheckpointFactory.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. - return moduleRegistry.registerModule(ManualApprovalTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // E) Register the ERC20DividendCheckpointFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the ERC20DividendCheckpoint contract. - return moduleRegistry.registerModule(ERC20DividendCheckpointFactory.address, {from: PolymathAccount}); - }).then(() => { - // F) Once the GeneralTransferManagerFactory 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(GeneralTransferManagerFactory.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(() => { - // 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. - // 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 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. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(GeneralPermissionManagerFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // G) Once the EtherDividendCheckpointFactory 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(EtherDividendCheckpointFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the ERC20DividendCheckpointFactory 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(ERC20DividendCheckpointFactory.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. - // 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(() => { - // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). - return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, 0, 0, CappedSTOLogic.address, {from: PolymathAccount}) - }).then(() => { - // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the CappedSTOFactory contract. - return moduleRegistry.registerModule(CappedSTOFactory.address, {from: PolymathAccount}) - }).then(()=>{ - // G) Once the CappedSTOFactory 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(CappedSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). - return deployer.deploy(USDTieredSTOFactory, 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. - return moduleRegistry.registerModule(USDTieredSTOFactory.address, {from: PolymathAccount}) - }).then(()=>{ - // J) Once the USDTieredSTOFactory 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(USDTieredSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - return polymathRegistry.changeAddress("PolyUsdOracle", POLYOracle, {from: PolymathAccount}); - }).then(() => { - return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, {from: PolymathAccount}); - }).then(() => { - return deployer.deploy(SecurityToken, 'a', 'a', 18, 1, 'a', polymathRegistry.address, {from: PolymathAccount}); - }).then(() => { - console.log('\n'); - console.log(` + // POLYMATH NETWORK Configuration :: DO THIS ONLY ONCE + // A) Deploy the PolymathRegistry contract + return deployer + .deploy(PolymathRegistry, { from: PolymathAccount }) + .then(() => { + return PolymathRegistry.deployed(); + }) + .then(_polymathRegistry => { + polymathRegistry = _polymathRegistry; + return polymathRegistry.changeAddress("PolyToken", PolyToken, { from: PolymathAccount }); + }) + .then(() => { + // Deploy libraries + return deployer.deploy(TokenLib, { from: PolymathAccount }); + }) + .then(() => { + // Link libraries + deployer.link(TokenLib, SecurityToken); + deployer.link(TokenLib, STFactory); + // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) + return deployer.deploy(ModuleRegistry, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(ModuleRegistryProxy, { from: PolymathAccount }); + }) + .then(() => { + return ModuleRegistryProxy.at(ModuleRegistryProxy.address); + }) + .then(moduleRegistryProxy => { + let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [polymathRegistry.address, PolymathAccount]); + return moduleRegistryProxy.upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, { from: PolymathAccount }); + }) + .then(() => { + return ModuleRegistry.at(ModuleRegistryProxy.address); + }) + .then(moduleRegistryInstance => { + moduleRegistry = moduleRegistryInstance; + // 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, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the GeneralPermissionManagerLogic Contract (Factory used to generate the GeneralPermissionManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralPermissionManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the CountTransferManagerLogic Contract (Factory used to generate the CountTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(CountTransferManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the ManualApprovalTransferManagerLogic Contract (Factory used to generate the ManualApprovalTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(ManualApprovalTransferManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the PercentageTransferManagerLogic Contract (Factory used to generate the PercentageTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(PercentageTransferManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // 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, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // 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, nullAddress, nullAddress, { 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, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the CappedSTOLogic Contract (Factory used to generate the CappedSTO contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(CappedSTOLogic, nullAddress, nullAddress, { 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, new BN(0), new BN(0), new BN(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) + return deployer.deploy(GeneralPermissionManagerFactory, new BN(0), new BN(0), new BN(0), GeneralPermissionManagerLogic.address, { + from: PolymathAccount + }); + }) + .then(() => { + // 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, new BN(0), new BN(0), new BN(0), CountTransferManagerLogic.address, { + 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) + return deployer.deploy(PercentageTransferManagerFactory, new BN(0), new BN(0), new BN(0), PercentageTransferManagerLogic.address, { + 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) + return deployer.deploy(EtherDividendCheckpointFactory, new BN(0), new BN(0), new BN(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, new BN(0), new BN(0), new BN(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) + return deployer.deploy(ManualApprovalTransferManagerFactory, new BN(0), new BN(0), new BN(0), ManualApprovalTransferManagerLogic.address, { + from: PolymathAccount + }); + }) + .then(() => { + // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. + return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // K) Deploy the FeatureRegistry contract to control feature switches + return deployer.deploy(FeatureRegistry, PolymathRegistry.address, { from: PolymathAccount }); + }) + .then(() => { + // Assign the address into the FeatureRegistry key + return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, { from: PolymathAccount }); + }) + .then(() => { + // J) Deploy the SecurityTokenRegistry contract (Used to hold the deployed secuirtyToken details. It also act as the interface to deploy the SecurityToken) + return deployer.deploy(SecurityTokenRegistry, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(SecurityTokenRegistryProxy, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(STRGetter, {from: PolymathAccount}); + }) + .then(() => { + return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address); + }) + .then((securityTokenRegistryProxy) => { + let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [ + PolymathRegistry.address, + STFactory.address, + initRegFee, + initRegFee, + PolymathAccount, + STRGetter.address + ]); + return securityTokenRegistryProxy.upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, { + from: PolymathAccount + }); + }) + .then(() => { + // Assign the address into the SecurityTokenRegistry key + return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, { from: PolymathAccount }); + }) + .then(() => { + // Update all addresses into the registry contract by calling the function updateFromregistry + return moduleRegistry.updateFromRegistry({ 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. + return moduleRegistry.registerModule(PercentageTransferManagerFactory.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. + return moduleRegistry.registerModule(CountTransferManagerFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // 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(() => { + // 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(GeneralPermissionManagerFactory.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. + return moduleRegistry.registerModule(EtherDividendCheckpointFactory.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. + return moduleRegistry.registerModule(ManualApprovalTransferManagerFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // E) Register the ERC20DividendCheckpointFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the ERC20DividendCheckpoint contract. + return moduleRegistry.registerModule(ERC20DividendCheckpointFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // F) Once the GeneralTransferManagerFactory 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(GeneralTransferManagerFactory.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(() => { + // 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. + // 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 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. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(GeneralPermissionManagerFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + // G) Once the EtherDividendCheckpointFactory 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(EtherDividendCheckpointFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + // G) Once the ERC20DividendCheckpointFactory 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(ERC20DividendCheckpointFactory.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. + // 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(() => { + // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). + return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, new BN(0), new BN(0), CappedSTOLogic.address, { from: PolymathAccount }); + }) + .then(() => { + // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the CappedSTOFactory contract. + return moduleRegistry.registerModule(CappedSTOFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // G) Once the CappedSTOFactory 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(CappedSTOFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). + return deployer.deploy(USDTieredSTOFactory, usdTieredSTOSetupCost, new BN(0), new BN(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. + return moduleRegistry.registerModule(USDTieredSTOFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // J) Once the USDTieredSTOFactory 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(USDTieredSTOFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + return polymathRegistry.changeAddress("PolyUsdOracle", POLYOracle, { from: PolymathAccount }); + }) + .then(() => { + return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(SecurityToken, "a", "a", 18, 1, "a", polymathRegistry.address, { from: PolymathAccount }); + }) + .then(() => { + console.log("\n"); + console.log(` ----------------------- Polymath Network Smart Contracts: ----------------------- PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} @@ -373,7 +493,7 @@ module.exports = function (deployer, network, accounts) { ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} --------------------------------------------------------------------------------- `); - console.log('\n'); - // -------- END OF POLYMATH NETWORK Configuration -------// - }); -} + console.log("\n"); + // -------- END OF POLYMATH NETWORK Configuration -------// + }); +}; diff --git a/package.json b/package.json index 239f73f43..809f9148e 100644 --- a/package.json +++ b/package.json @@ -67,12 +67,12 @@ "ethereumjs-testrpc": "^6.0.3", "ethers": "^4.0.7", "fs": "0.0.2", - "openzeppelin-solidity": "2.0.0", + "openzeppelin-solidity": "^2.1.0-rc.2", + "pify": "^4.0.1", "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" @@ -87,14 +87,15 @@ "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.4", "mocha-junit-reporter": "^1.18.0", - "prettier": "^1.14.3", + "prettier": "^1.15.3", + "prettier-plugin-solidity-refactor": "^1.0.0-alpha.10", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", "solium": "^1.1.6", - "truffle": "4.1.14", + "truffle": "^5.0.0", "truffle-wallet-provider": "0.0.5" }, "greenkeeper": { diff --git a/scripts/calculateSize.js b/scripts/calculateSize.js index 46cf238db..997c34547 100644 --- a/scripts/calculateSize.js +++ b/scripts/calculateSize.js @@ -1,12 +1,10 @@ -const fs = require('fs'); -const path = require('path'); +const fs = require("fs"); +const path = require("path"); var size = new Array(); - - function readFiles() { - if (fs.existsSync('./build/contracts/')) { - let files = fs.readdirSync('./build/contracts/'); + if (fs.existsSync("./build/contracts/")) { + let files = fs.readdirSync("./build/contracts/"); return files; } else { console.log("Directory doesn't exists"); @@ -15,16 +13,16 @@ function readFiles() { async function printSize() { let files = readFiles(); - files.forEach((item) => { + files.forEach(item => { let content = JSON.parse(fs.readFileSync(`./build/contracts/${item}`).toString()).deployedBytecode; - let sizeInKB = ((content.toString()).length / 2) / 1024; + let sizeInKB = content.toString().length / 2 / 1024; size.push(sizeInKB); }); console.log(`NOTE- Maximum size of contracts allowed to deloyed on the Ethereum mainnet is 24 KB(EIP170)`); console.log(`---- Size of the contracts ----`); - for(let i = 0; i < files.length; i++) { - console.log(`${path.basename(files[i], '.json')} - ${size[i]} KB`); + for (let i = 0; i < files.length; i++) { + console.log(`${path.basename(files[i], ".json")} - ${size[i]} KB`); } } -printSize(); \ No newline at end of file +printSize(); diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js index c339bf095..92d43a56f 100644 --- a/scripts/compareStorageLayout.js +++ b/scripts/compareStorageLayout.js @@ -1,139 +1,140 @@ -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); +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; +prompt.get(["LogicContract", "ProxyContract"], async (err, result) => { + let logicContract; + let proxyContract; - const fileList = walkSync('./contracts', []); + const fileList = walkSync("./contracts", []); - let paths = findPath(result.LogicContract, result.ProxyContract, fileList); + let paths = findPath(result.LogicContract, result.ProxyContract, fileList); - if (paths.length == 2) { - - console.log("Contracts exists \n"); - - await flatContracts(paths); + if (paths.length == 2) { + console.log("Contracts exists \n"); - 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'); - } + await flatContracts(paths); - let logicInput = { - 'contracts': logicContract - } - let proxyInput = { - 'contracts': proxyContract - } + 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"); + } - console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); + let logicInput = { + contracts: logicContract + }; + let proxyInput = { + contracts: proxyContract + }; - } else { - console.log("Contracts doesn't exists"); - } + 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); + if (_input.children) { + for (var i = 0; i < _input.children.length; i++) { + traverseAST(_input.children[i], _elements); + } } - } - _elements.push(_input); + _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; + 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; + 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 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; + 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]); + 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; -} + 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`)); + 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/encoders/encode_CappedSTO.js b/scripts/encoders/encode_CappedSTO.js index 12527a1e1..dc9d054c2 100644 --- a/scripts/encoders/encode_CappedSTO.js +++ b/scripts/encoders/encode_CappedSTO.js @@ -1,10 +1,10 @@ -const Web3 = require('web3'); +const Web3 = require("web3"); -if (typeof web3 !== 'undefined') { - web3 = new Web3(web3.currentProvider); +if (typeof web3 !== "undefined") { + web3 = new Web3(web3.currentProvider); } else { - // set the provider you want from Web3.providers - web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + // set the provider you want from Web3.providers + web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); } let startTime = process.argv.slice(2)[0]; @@ -13,33 +13,42 @@ let cap = process.argv.slice(2)[2]; let rate = process.argv.slice(2)[3]; let wallet = process.argv.slice(2)[4]; - -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: '_fundRaiseType' - },{ - type: 'address', - name: '_polyToken' - },{ - type: 'address', - name: '_fundsReceiver' - } +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: "_fundRaiseType" + }, + { + type: "address", + name: "_polyToken" + }, + { + type: "address", + name: "_fundsReceiver" + } ] - }, [startTime, endTime, web3.utils.toWei(cap, 'ether'), rate,0,0,wallet]); + }, + [startTime, endTime, web3.utils.toWei(cap, "ether"), rate, 0, 0, wallet] +); - console.log(bytesSTO); +console.log(bytesSTO); diff --git a/scripts/patch.js b/scripts/patch.js index b1bbbcb3f..bf006d160 100644 --- a/scripts/patch.js +++ b/scripts/patch.js @@ -1,25 +1,26 @@ -const fs = require('fs'); -const request = require('request'); -const regex = /node ..\/n(.)*,/gmi; -const regex2 = /truffle test(.)*,/gmi; +const fs = require("fs"); +const request = require("request"); +const regex = /node ..\/n(.)*,/gim; +const regex2 = /truffle test(.)*,/gim; -request('https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js').pipe(fs.createWriteStream('node_modules\\solidity-coverage\\lib\\app.js')); +request("https://raw.githubusercontent.com/maxsam4/solidity-coverage/relative-path/lib/app.js").pipe( + fs.createWriteStream("node_modules\\solidity-coverage\\lib\\app.js") +); -fs.readFile('.solcover.js', 'utf8', function (err,data) { - if (err) { - return console.log(err); - } +fs.readFile(".solcover.js", "utf8", function(err, data) { + if (err) { + return console.log(err); + } - let testCommand = 'truffle test --network coverage'; - fs.readdirSync('./test').forEach(file => { - if(file != 'a_poly_oracle.js' && file != 's_v130_to_v140_upgrade.js') - testCommand = testCommand + ' test\\\\' + file; - }); - testCommand = testCommand + '\','; - let result = data.replace(regex2, testCommand); - result = result.replace(regex, testCommand); + let testCommand = "truffle test --network coverage"; + fs.readdirSync("./test").forEach(file => { + if (file != "a_poly_oracle.js" && file != "s_v130_to_v140_upgrade.js") testCommand = testCommand + " test\\\\" + file; + }); + testCommand = testCommand + "',"; + let result = data.replace(regex2, testCommand); + result = result.replace(regex, testCommand); - fs.writeFile('.solcover.js', result, 'utf8', function (err) { - if (err) return console.log(err); - }); -}); \ No newline at end of file + fs.writeFile(".solcover.js", result, "utf8", function(err) { + if (err) return console.log(err); + }); +}); diff --git a/scripts/test.sh b/scripts/test.sh index 9f595d0ba..f44a7af89 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -57,7 +57,7 @@ start_testrpc() { ) if [ "$COVERAGE" = true ]; then - node_modules/.bin/testrpc-sc --gasLimit 0xfffffffffff --port "$testrpc_port" "${accounts[@]}" > /dev/null & + node_modules/.bin/testrpc-sc --gasLimit 0xfffffffff --port "$testrpc_port" "${accounts[@]}" > /dev/null & else node_modules/.bin/ganache-cli --gasLimit 8000000 "${accounts[@]}" > /dev/null & fi @@ -90,6 +90,7 @@ 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 + curl -o node_modules/solidity-parser-sc/build/parser.js https://raw.githubusercontent.com/maxsam4/solidity-parser/solidity-0.5/build/parser.js node_modules/.bin/solidity-coverage if [ "$CIRCLECI" = true ]; then cat coverage/lcov.info | node_modules/.bin/coveralls diff --git a/scripts/tokenInfo-v1.js b/scripts/tokenInfo-v1.js index ea14a7efe..490fccfee 100644 --- a/scripts/tokenInfo-v1.js +++ b/scripts/tokenInfo-v1.js @@ -1,18 +1,31 @@ const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/")); -var request = require('request-promise') +var request = require("request-promise"); -const securityTokenABI = JSON.parse(require('fs').readFileSync('../CLI/data/SecurityToken1-4-0.json').toString()).abi; -const generalTransferManagerABI = JSON.parse(require('fs').readFileSync('../CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; +const securityTokenABI = JSON.parse( + require("fs") + .readFileSync("../CLI/data/SecurityToken1-4-0.json") + .toString() +).abi; +const generalTransferManagerABI = JSON.parse( + require("fs") + .readFileSync("../CLI/data/GeneralTransferManager1-4-0.json") + .toString() +).abi; async function getTokens() { 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)'); + 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); } } @@ -21,17 +34,22 @@ 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()); + 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 getLogsFromEtherscan(gtmRes.moduleAddress, web3.utils.hexToNumber('0x5C5C18'), 'latest', 'LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); + let gtmEvents = await getLogsFromEtherscan( + gtmRes.moduleAddress, + web3.utils.hexToNumber("0x5C5C18"), + "latest", + "LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)" + ); console.log("Count of GeneralTransferManager Events: " + gtmEvents.length); console.log("Modules Attached (TransferManager):"); await getModules(2, token); @@ -41,7 +59,7 @@ async function getInfo(tokenAddress) { await getModules(3, token); console.log("Modules Attached (Checkpoint):"); await getModules(4, token); - console.log("") + console.log(""); console.log(); console.log(); } @@ -65,19 +83,19 @@ async function getModules(type, token) { } async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignature) { - let urlDomain = 'api'; + let urlDomain = "api"; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { - module: 'logs', - action: 'getLogs', + module: "logs", + action: "getLogs", fromBlock: _fromBlock, toBlock: _toBlock, address: _address, topic0: web3.utils.sha3(_eventSignature), - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + apikey: "THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559" }, - method: 'GET', + method: "GET", json: true }; let data = await request(options); @@ -85,20 +103,20 @@ async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignat } async function getABIfromEtherscan(_address) { - let urlDomain = 'api'; + let urlDomain = "api"; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { - module: 'contract', - action: 'getabi', + module: "contract", + action: "getabi", address: _address, - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + apikey: "THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559" }, - method: 'GET', + method: "GET", json: true }; let data = await request(options); return JSON.parse(data.result); } -getTokens(); \ No newline at end of file +getTokens(); diff --git a/scripts/tokenInfo-v2.js b/scripts/tokenInfo-v2.js index 1d0f9236f..749bb299d 100644 --- a/scripts/tokenInfo-v2.js +++ b/scripts/tokenInfo-v2.js @@ -1,19 +1,32 @@ const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/")); -var request = require('request-promise') +var request = require("request-promise"); -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 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; async function getTokens() { const securityTokenRegistryAddress = "0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97"; const securityTokenRegistryABI = await getABIfromEtherscan(securityTokenRegistryAddress); const securityTokenRegistry = new web3.eth.Contract(securityTokenRegistryABI, securityTokenRegistryAddress); - let logs = await getLogsFromEtherscan(securityTokenRegistry.options.address, 0, 'latest', 'NewSecurityToken(string,string,address,address,uint256,address,bool,uint256)'); + let logs = await getLogsFromEtherscan( + securityTokenRegistry.options.address, + 0, + "latest", + "NewSecurityToken(string,string,address,address,uint256,address,bool,uint256)" + ); console.log(logs.length); 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); } } @@ -23,25 +36,30 @@ async function getInfo(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("Details: " + await token.methods.tokenDetails().call()); - console.log("Symbol: " + await token.methods.symbol().call()); - console.log("Granularity: " + await token.methods.granularity().call()); - console.log("Total Supply: " + await token.methods.totalSupply().call()); - console.log("Transfers Frozen: " + await token.methods.transfersFrozen().call()); - console.log("Minting Frozen: " + await token.methods.mintingFrozen().call()); + console.log("Name: " + (await token.methods.name().call())); + console.log("Details: " + (await token.methods.tokenDetails().call())); + console.log("Symbol: " + (await token.methods.symbol().call())); + console.log("Granularity: " + (await token.methods.granularity().call())); + console.log("Total Supply: " + (await token.methods.totalSupply().call())); + console.log("Transfers Frozen: " + (await token.methods.transfersFrozen().call())); + console.log("Minting Frozen: " + (await token.methods.mintingFrozen().call())); let controllerDisabled = await token.methods.controllerDisabled().call(); if (controllerDisabled) { console.log("Controller disabled: YES"); } else { - console.log("Controller: " + await token.methods.controller().call()); + console.log("Controller: " + (await token.methods.controller().call())); } - console.log("Investors: " + await token.methods.getInvestorCount().call()); - console.log("Latest Checkpoint: " + await token.methods.currentCheckpointId().call()); + console.log("Investors: " + (await token.methods.getInvestorCount().call())); + console.log("Latest Checkpoint: " + (await token.methods.currentCheckpointId().call())); let gtmEventsCount = 0; - let gtmModules = await token.methods.getModulesByName(web3.utils.toHex('GeneralTransferManager')).call(); + let gtmModules = await token.methods.getModulesByName(web3.utils.toHex("GeneralTransferManager")).call(); for (const m of gtmModules) { - let gtmEvents = await getLogsFromEtherscan(m, 9299699, 'latest', 'ModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); + let gtmEvents = await getLogsFromEtherscan( + m, + 9299699, + "latest", + "ModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)" + ); gtmEventsCount += gtmEvents.length; } console.log("Count of GeneralTransferManager Events: " + gtmEventsCount); @@ -69,19 +87,19 @@ async function getModules(type, token) { } async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignature) { - let urlDomain = 'api'; + let urlDomain = "api"; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { - module: 'logs', - action: 'getLogs', + module: "logs", + action: "getLogs", fromBlock: _fromBlock, toBlock: _toBlock, address: _address, topic0: web3.utils.sha3(_eventSignature), - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + apikey: "THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559" }, - method: 'GET', + method: "GET", json: true }; let data = await request(options); @@ -89,20 +107,20 @@ async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignat } async function getABIfromEtherscan(_address) { - let urlDomain = 'api'; + let urlDomain = "api"; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { - module: 'contract', - action: 'getabi', + module: "contract", + action: "getabi", address: _address, - apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' + apikey: "THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559" }, - method: 'GET', + method: "GET", json: true }; let data = await request(options); return JSON.parse(data.result); } -getTokens(); \ No newline at end of file +getTokens(); diff --git a/test/a_poly_oracle.js b/test/a_poly_oracle.js index 6363fe151..025b6ec72 100644 --- a/test/a_poly_oracle.js +++ b/test/a_poly_oracle.js @@ -5,10 +5,10 @@ import { increaseTime } from "./helpers/time"; import { catchRevert } from "./helpers/exceptions"; const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("PolyOracle", accounts => { +contract("PolyOracle", async (accounts) => { let I_PolyOracle; let owner; const URL = @@ -52,41 +52,43 @@ contract("PolyOracle", accounts => { describe("Scheduling test cases", async () => { it("Should schedule the timing of the call - fails - non owner", async () => { let timeScheduling = [ - latestTime() + duration.minutes(1), - latestTime() + duration.minutes(2), - latestTime() + duration.minutes(3) + await latestTime() + duration.minutes(1), + await latestTime() + duration.minutes(2), + await latestTime() + duration.minutes(3) ]; - await catchRevert(I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, { from: accounts[1], value: web3.utils.toWei("2") })); + await catchRevert(I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, { from: accounts[1], value: new BN(web3.utils.toWei("2")) })); }); it("Should schedule the timing of the call - fails - no value", async () => { let timeScheduling = [ - latestTime() + duration.minutes(1), - latestTime() + duration.minutes(2), - latestTime() + duration.minutes(3) + await latestTime() + duration.minutes(1), + await latestTime() + duration.minutes(2), + await latestTime() + duration.minutes(3) ]; await catchRevert(I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, { from: owner })); }); 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()); + let blockNo = await latestBlock(); + let tx = await I_PolyOracle.schedulePriceUpdatesFixed([], { from: owner, value: new BN(web3.utils.toWei("1")) }); + assert.isAtMost(tx.logs[0].args._time.toNumber(), await latestTime()); // await increaseTime(50); - const logNewPriceWatcher = await promisifyLogWatch(I_PolyOracle.PriceUpdated({ fromBlock: blockNo }), 1); + const logNewPriceWatcher = (await I_PolyOracle.getPastEvents('PriceUpdated', {filter: {from: blockNo}}))[0]; // 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" + "Success! Current price is: " + + logNewPriceWatcher.args._price.div(new BN(10).pow(new BN(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 blockNo = await latestBlock(); + let timeScheduling = [await latestTime() + duration.seconds(10), await latestTime() + duration.seconds(20)]; + let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, { from: owner, value: new BN(web3.utils.toWei("1.5")) }); let event_data = tx.logs; @@ -97,34 +99,34 @@ contract("PolyOracle", accounts => { } // 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 logNewPriceWatcher = (await I_PolyOracle.getPastEvents('PriceUpdated', {filter: {from: blockNo}}))[1]; 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"); + console.log("Success! Current price is: " + log.args._price.div(new BN(10).pow(new BN(18))).toNumber() + " USD/POLY"); }); it("Should schedule to call using iters - fails", async () => { - await catchRevert(I_PolyOracle.schedulePriceUpdatesRolling(latestTime() + 10, 30, 2, { from: accounts[6] })); + await catchRevert(I_PolyOracle.schedulePriceUpdatesRolling(await latestTime() + 10, 30, 2, { from: accounts[6] })); }); it("Should schedule to call using iters", async () => { - let blockNo = latestBlock(); + let blockNo = await latestBlock(); console.log(`Latest Block number of the local chain:${blockNo}`); - let tx = await I_PolyOracle.schedulePriceUpdatesRolling(latestTime() + 10, 10, 2, { from: owner }); + let tx = await I_PolyOracle.schedulePriceUpdatesRolling(await 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); + assert.isAtMost(time.toNumber(), await 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 logNewPriceWatcher = (await I_PolyOracle.getPastEvents('PriceUpdated', {filter: {from: blockNo}}))[1]; 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"); + console.log("Success! Current price is: " + log.args._price.div(new BN(10).pow(new BN(18))).toNumber() + " USD/POLY"); latestPrice = log.args._price; }); }); @@ -154,26 +156,26 @@ contract("PolyOracle", accounts => { }); it("Should change the sanity bounds manually - fails - bad owner", async () => { - await catchRevert(I_PolyOracle.setSanityBounds(new BigNumber(25).times(new BigNumber(10).pow(16)), { from: accounts[6] })); + await catchRevert(I_PolyOracle.setSanityBounds(new BN(25).mul(new BN(10).pow(16)), { from: accounts[6] })); }); 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 }); + await I_PolyOracle.setSanityBounds(new BN(25).mul(new BN(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()); + assert.equal(sanityBounds.toNumber(), new BN(25).mul(new BN(10).pow(16)).toNumber()); }); it("Should change the gas price manually - fails - bad owner", async () => { - await catchRevert(I_PolyOracle.setGasPrice(new BigNumber(60).times(new BigNumber(10).pow(9)), { from: accounts[6] })); + await catchRevert(I_PolyOracle.setGasPrice(new BN(60).mul(new BN(10).pow(9)), { from: accounts[6] })); }); 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") }); + await I_PolyOracle.setGasPrice(new BN(60).mul(new BN(10).pow(9)), { from: owner }); + let blockNo = await latestBlock(); + let timeScheduling = [await latestTime() + duration.seconds(10), await latestTime() + duration.seconds(20)]; + let tx = await I_PolyOracle.schedulePriceUpdatesFixed(timeScheduling, { from: owner, value: new BN(web3.utils.toWei("2")) }); let event_data = tx.logs; @@ -182,13 +184,14 @@ contract("PolyOracle", accounts => { 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); + const logNewPriceWatcher = (await I_PolyOracle.getPastEvents('PriceUpdated', {filter: {from: 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" + "Success! Current price is: " + + logNewPriceWatcher.args._price.div(new BN(10).pow(new BN(18))).toNumber() + + " USD/POLY" ); // assert.isTrue(false); }); @@ -243,14 +246,16 @@ contract("PolyOracle", accounts => { }); 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); + let blockNo = await latestBlock(); + let tx = await I_PolyOracle.schedulePriceUpdatesFixed([], { from: owner, value: new BN(web3.utils.toWei("1")) }); + assert.isAtMost(tx.logs[0].args._time.toNumber(), await latestTime()); + const logNewPriceWatcher = (await I_PolyOracle.getPastEvents('PriceUpdated', {filter: {from: blockNo}}))[0]; 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" + "Success! Current price is: " + + logNewPriceWatcher.args._price.div(new BN(10).pow(new BN(18))).toNumber() + + " USD/POLY" ); // assert.isTrue(false); }); diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index ab8f32688..94d0d4368 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -1,5 +1,5 @@ import latestTime from "./helpers/latestTime"; -import { duration, ensureException, promisifyLogWatch, latestBlock } from "./helpers/utils"; +import { duration, ensureException, latestBlock } from "./helpers/utils"; import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeModuleCall } from "./helpers/encodeCall"; import { setUpPolymathNetwork, deployGPMAndVerifyed, deployCappedSTOAndVerifyed } from "./helpers/createInstances"; @@ -12,13 +12,14 @@ const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; +let toBN = Web3.utils.toBN; 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 => { +contract("CappedSTO", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_investor1; @@ -79,15 +80,15 @@ contract("CappedSTO", accounts => { const budget = 0; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(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 = web3.utils.toWei("1000"); + const cap = new BN(web3.utils.toWei("10000")); + const rate = new BN(web3.utils.toWei("1000")); const E_fundRaiseType = 0; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -96,15 +97,17 @@ contract("CappedSTO", accounts => { let startTime_POLY2; let endTime_POLY2; let blockNo; - const P_cap = web3.utils.toWei("50000"); + const P_cap = new BN(web3.utils.toWei("50000")); const P_fundRaiseType = 1; - const P_rate = web3.utils.toWei("5"); - const cappedSTOSetupCost = web3.utils.toWei("20000", "ether"); + const P_rate = new BN(web3.utils.toWei("5")); + const cappedSTOSetupCost = new BN(web3.utils.toWei("20000", "ether")); const maxCost = cappedSTOSetupCost; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; + let currentTime; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; account_investor1 = accounts[4]; @@ -114,7 +117,6 @@ contract("CappedSTO", accounts => { token_owner = account_issuer; let instances = await setUpPolymathNetwork(account_polymath, token_owner); - [ I_PolymathRegistry, I_PolyToken, @@ -131,7 +133,7 @@ contract("CappedSTO", accounts => { ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, new BN(0)); // STEP 6: Deploy the CappedSTOFactory @@ -166,16 +168,15 @@ contract("CappedSTO", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken_ETH = SecurityToken.at(tx.logs[2].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({ from: _blockNo }), 1); + I_SecurityToken_ETH = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + const log = (await I_SecurityToken_ETH.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // 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"); @@ -183,51 +184,49 @@ contract("CappedSTO", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should mint the tokens before attaching the STO", async () => { - await catchRevert( - I_SecurityToken_ETH.mint(address_zero, web3.utils.toWei("1"), { from: token_owner }) - ); + await catchRevert(I_SecurityToken_ETH.mint(address_zero, new BN(new BN(web3.utils.toWei("1"))), { from: token_owner })); }); 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 startTime = await 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 bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, new BN(0), [E_fundRaiseType], account_fundsReceiver]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should fail to launch the STO due to rate is 0", async () => { - let startTime = latestTime() + duration.days(1); + let startTime = await 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 bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, new BN(0), [E_fundRaiseType], account_fundsReceiver]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should fail to launch the STO due funds reciever account 0x", async () => { - let startTime = latestTime() + duration.days(1); + let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], address_zero]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should fail to launch the STO due to raise type of 0 length", async () => { - let startTime = latestTime() + duration.days(1); + let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [], account_fundsReceiver]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should fail to launch the STO due to startTime > endTime", async () => { @@ -240,26 +239,26 @@ contract("CappedSTO", accounts => { account_fundsReceiver ]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should fail to launch the STO due to cap is of 0 securityToken", async () => { - let startTime = latestTime() + duration.days(1); + let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, new BN(0), rate, [E_fundRaiseType], account_fundsReceiver]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); - it("Should fail to launch the STO due to different value incompare to getInitFunction", async() => { - let startTime = latestTime() + duration.days(1); + it("Should fail to launch the STO due to different value incompare to getInitFunction", async () => { + let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(['uint256', 'uint256', 'uint256'], [startTime, endTime, 0, ]); - await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + let bytesSTO = encodeModuleCall(["uint256", "uint256", "uint256"], [startTime, endTime, 0]); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should successfully attach the STO module to the security token", async () => { - startTime_ETH1 = latestTime() + duration.days(1); + startTime_ETH1 = await latestTime() + duration.days(1); endTime_ETH1 = startTime_ETH1 + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [ startTime_ETH1, @@ -269,26 +268,28 @@ contract("CappedSTO", accounts => { [E_fundRaiseType], account_fundsReceiver ]); - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(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)); + I_CappedSTO_Array_ETH.push(await CappedSTO.at(tx.logs[3].args._module)); }); - it("Should call the configure function -- fail because of the bad owner", async()=> { + it("Should call the configure function -- fail because of the bad owner", async () => { await catchRevert( - I_CappedSTO_Array_ETH[0].configure(startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver, {from: account_polymath }) + I_CappedSTO_Array_ETH[0].configure(startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver, { + from: account_polymath + }) ); - }) + }); }); 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()).toNumber(), rate, "STO Configuration doesn't set as expected"); + assert.equal(await I_CappedSTO_Array_ETH[0].startTime(), startTime_ETH1, "1STO Configuration doesn't set as expected"); + assert.equal(await I_CappedSTO_Array_ETH[0].endTime(), endTime_ETH1, "2STO Configuration doesn't set as expected"); + assert.equal((await I_CappedSTO_Array_ETH[0].cap()).toString(), cap.toString(), "3STO Configuration doesn't set as expected"); + assert.equal((await I_CappedSTO_Array_ETH[0].rate()).toString(), rate.toString(), "4STO Configuration doesn't set as expected"); assert.equal( await I_CappedSTO_Array_ETH[0].fundRaiseTypes.call(E_fundRaiseType), true, @@ -299,90 +300,66 @@ contract("CappedSTO", accounts => { describe("Buy tokens", async () => { it("Should buy the tokens -- failed due to startTime is greater than Current time", async () => { - await catchRevert( - web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("1", "ether") - }) - ); - }); - - it("Should buy the tokens -- failed due to invested amount is zero", async () => { - await catchRevert( - web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("0", "ether") - }) - ); + await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor1, { from: account_investor1, value: new BN(web3.utils.toWei("1", "ether")) })); + await increaseTime(duration.days(1)); }); it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { - await catchRevert( - web3.eth.sendTransaction({ - from: account_investor1, - to: I_CappedSTO_Array_ETH[0].address, - value: web3.utils.toWei("1", "ether") - }) - ); - }); + await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor1, { from: account_investor1, value: new BN(web3.utils.toWei("1", "ether")) })); - it("Should Buy the tokens", async () => { - blockNo = latestBlock(); - fromTime = latestTime(); - toTime = latestTime() + duration.days(15); + blockNo = await latestBlock(); + fromTime = await latestTime(); + toTime = await 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 }); 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({ + it("Should buy the tokens -- failed due to invested amount is zero", async () => { + await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor1, { from: account_investor1, value: new BN(web3.utils.toWei("0", "ether")) })); + }); + + it("Should Buy the tokens", async () => { + + balanceOfReceiver = new BN(await web3.eth.getBalance(account_fundsReceiver)); + + await I_CappedSTO_Array_ETH[0].buyTokens(account_investor1, { 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].getRaised.call(ETH)).div(new BN(10).pow(new BN(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); - assert.equal((await I_CappedSTO_Array_ETH[0].getTokensSold.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000); + assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 1000); + assert.equal((await I_CappedSTO_Array_ETH[0].getTokensSold.call()).div(new BN(10).pow(new BN(18))).toNumber(), 1000); }); it("Verification of the event Token Purchase", async () => { - const log = await promisifyLogWatch(I_CappedSTO_Array_ETH[0].TokenPurchase({ from: blockNo }), 1); - + const log = (await I_CappedSTO_Array_ETH[0].getPastEvents('TokenPurchase', {filter: {from: blockNo}}))[0]; 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"); + assert.equal(log.args.amount.div(new BN(10).pow(new BN(18))).toNumber(), 1000, "Wrong No. token get dilivered"); }); - it("Should fail to buy the tokens -- Because fundRaiseType is ETH not POLY", async ()=> { - await I_PolyToken.getTokens(web3.utils.toWei("500"), account_investor1); - await I_PolyToken.approve(I_CappedSTO_Array_ETH[0].address, web3.utils.toWei("500"), {from: account_investor1}); - await catchRevert( - I_CappedSTO_Array_ETH[0].buyTokensWithPoly(web3.utils.toWei("500"), {from: account_investor1}) - ); - }) + it("Should fail to buy the tokens -- Because fundRaiseType is ETH not POLY", async () => { + await I_PolyToken.getTokens(new BN(new BN(web3.utils.toWei("500"))), account_investor1); + await I_PolyToken.approve(I_CappedSTO_Array_ETH[0].address, new BN(new BN(web3.utils.toWei("500"))), { from: account_investor1 }); + await catchRevert(I_CappedSTO_Array_ETH[0].buyTokensWithPoly(new BN(new BN(web3.utils.toWei("500"))), { from: account_investor1 })); + }); it("Should pause the STO -- Failed due to wrong msg.sender", async () => { await catchRevert(I_CappedSTO_Array_ETH[0].pause({ from: account_investor1 })); }); it("Should pause the STO", async () => { - pauseTime = latestTime(); + pauseTime = await latestTime(); let tx = await I_CappedSTO_Array_ETH[0].pause({ from: account_issuer }); assert.isTrue(await I_CappedSTO_Array_ETH[0].paused.call()); }); @@ -393,7 +370,7 @@ contract("CappedSTO", accounts => { from: account_investor1, to: I_CappedSTO_Array_ETH[0].address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(web3.utils.toWei("1", "ether")) }) ); }); @@ -408,7 +385,7 @@ contract("CappedSTO", accounts => { }); it("Should buy the granular unit tokens and refund pending amount", async () => { - await I_SecurityToken_ETH.changeGranularity(10 ** 21, {from: token_owner}); + await I_SecurityToken_ETH.changeGranularity(new BN(10).pow(new BN(21)), { from: token_owner }); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, fromTime, @@ -420,60 +397,66 @@ contract("CappedSTO", accounts => { } ); 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); + let initBalance = new BN(await web3.eth.getBalance(account_investor2)); + tx = await I_CappedSTO_Array_ETH[0].buyTokens(account_investor2, { + from: account_investor2, + value: new BN(web3.utils.toWei("1.5", "ether")), + gasPrice: 1 + }); + let finalBalance = new BN(await web3.eth.getBalance(account_investor2)); + assert.equal( + finalBalance + .add(new BN(tx.receipt.gasUsed)) + .add(new BN(web3.utils.toWei("1", "ether"))) + .toString(), + initBalance.toString() + ); + await I_SecurityToken_ETH.changeGranularity(1, { from: token_owner }); + assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).div(new BN(10).pow(new BN(18))).toNumber(), 2); - assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000); + assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor2)).div(new BN(10).pow(new BN(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({ from: account_investor2, to: I_CappedSTO_Array_ETH[0].address, gas: 2100000, - value: web3.utils.toWei("8", "ether") + value: new BN(web3.utils.toWei("8", "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].getRaised.call(ETH)).div(new BN(10).pow(new BN(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); - await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor2, { value: web3.utils.toWei("81") })); + assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor2)).div(new BN(10).pow(new BN(18))).toNumber(), 9000); + await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor2, { value: new BN(web3.utils.toWei("81")) })); }); 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 = new BigNumber(newBalance) - .minus(balanceOfReceiver) - .toNumber(); + let op = new BN(newBalance).sub(balanceOfReceiver); assert.equal( - (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toNumber(), - op, + (await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toString(), + op.toString(), "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")); + assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); 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")); + assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(POLY)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); }); 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"); + let value = new BN(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 }); @@ -481,30 +464,30 @@ contract("CappedSTO", accounts => { }); 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"); + let initInvestorBalance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let initOwnerBalance = new BN(await I_PolyToken.balanceOf(token_owner)); + let initContractBalance = new BN(await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)); + let value = new BN(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_investor1)).toNumber(), - initInvestorBalance.toNumber(), + (await I_PolyToken.balanceOf(account_investor1)).toString(), + initInvestorBalance.toString(), "tokens are not transferred out from investor account" ); assert.equal( - (await I_PolyToken.balanceOf(token_owner)).toNumber(), + (await I_PolyToken.balanceOf(token_owner)).toString(), initOwnerBalance .add(value) .add(initContractBalance) - .toNumber(), + .toString(), "tokens are not added to the owner account" ); assert.equal( - (await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)).toNumber(), - 0, + (await I_PolyToken.balanceOf(I_CappedSTO_Array_ETH[0].address)).toString(), + new BN(0).toString(), "tokens are not trandfered out from STO contract" ); }); @@ -512,7 +495,7 @@ contract("CappedSTO", accounts => { 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); + startTime_ETH2 = await latestTime() + duration.days(1); endTime_ETH2 = startTime_ETH2 + duration.days(30); await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); @@ -525,18 +508,18 @@ contract("CappedSTO", accounts => { [E_fundRaiseType], account_fundsReceiver ]); - const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(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)); + I_CappedSTO_Array_ETH.push(await 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()).toNumber(), rate, "STO Configuration doesn't set as expected"); + assert.equal((await I_CappedSTO_Array_ETH[1].cap.call()).toString(), cap.toString(), "STO Configuration doesn't set as expected"); + assert.equal((await I_CappedSTO_Array_ETH[1].rate.call()).toString(), rate.toString(), "STO Configuration doesn't set as expected"); assert.equal( await I_CappedSTO_Array_ETH[1].fundRaiseTypes.call(E_fundRaiseType), true, @@ -545,7 +528,7 @@ contract("CappedSTO", accounts => { }); it("Should successfully whitelist investor 3", async () => { - balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); + balanceOfReceiver = new BN(await web3.eth.getBalance(account_fundsReceiver)); let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, { from: account_issuer, @@ -562,7 +545,7 @@ contract("CappedSTO", accounts => { // Buying on behalf of another user should fail await catchRevert( - I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from: account_issuer, value: web3.utils.toWei("1", "ether") }) + I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from: account_issuer, value: new BN(web3.utils.toWei("1", "ether")) }) ); }); @@ -573,37 +556,35 @@ contract("CappedSTO", accounts => { }); it("Should allow non-matching beneficiary -- failed because it is already active", async () => { - await catchRevert( - I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, { from: account_issuer }) - ); + await catchRevert(I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, { from: account_issuer })); }); 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") }); + await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from: account_issuer, value: new BN(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].getRaised.call(ETH)).div(new BN(10).pow(new BN(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); + assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor3)).div(new BN(10).pow(new BN(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 startTime = await 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 }); + await I_PolyToken.getTokens(new BN(cappedSTOSetupCost.mul(new BN(19))), token_owner); + await I_PolyToken.transfer(I_SecurityToken_ETH.address, new BN(cappedSTOSetupCost.mul(new BN(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 }); + const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(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)); + I_CappedSTO_Array_ETH.push(await CappedSTO.at(tx.logs[3].args._module)); } }); @@ -613,10 +594,10 @@ contract("CappedSTO", accounts => { 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") + value: new BN(web3.utils.toWei("1", "ether")) }); assert.equal( - (await I_CappedSTO_Array_ETH[STOIndex].getRaised.call(ETH)).dividedBy(new BigNumber(10).pow(18)).toNumber(), + (await I_CappedSTO_Array_ETH[STOIndex].getRaised.call(ETH)).div(new BN(10).pow(new BN(18))).toNumber(), 1 ); assert.equal(await I_CappedSTO_Array_ETH[STOIndex].investorCount.call(), 1); @@ -635,15 +616,15 @@ contract("CappedSTO", accounts => { 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[2].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken_POLY = SecurityToken.at(tx.logs[2].args._securityTokenAddress); - - const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({ from: _blockNo }), 1); + I_SecurityToken_POLY = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken_POLY.getPastEvents('ModuleAdded', {filter: {from: blockNo}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey); @@ -652,11 +633,11 @@ contract("CappedSTO", accounts => { it("POLY: Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("POLY: Should successfully attach the STO module to the security token", async () => { - startTime_POLY1 = latestTime() + duration.days(2); + startTime_POLY1 = await latestTime() + duration.days(2); endTime_POLY1 = startTime_POLY1 + duration.days(30); await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); @@ -671,11 +652,11 @@ contract("CappedSTO", accounts => { account_fundsReceiver ]); - const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(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)); + I_CappedSTO_Array_POLY.push(await CappedSTO.at(tx.logs[3].args._module)); }); }); @@ -684,90 +665,85 @@ contract("CappedSTO", accounts => { assert.equal( (await I_CappedSTO_Array_POLY[0].startTime.call()).toNumber(), startTime_POLY1, - "STO Configuration doesn't set as expected" + "1STO 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" + "2STO 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" + (await I_CappedSTO_Array_POLY[0].cap.call()).div(new BN(10).pow(new BN(18))).toString(), + new BN(P_cap).div(new BN(10).pow(new BN(18))), + "3STO 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].rate.call()).toString(), new BN(P_rate).toString(), "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" + "4STO 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(); + await I_PolyToken.getTokens(new BN(10).pow(new BN(22)), account_investor1); + blockNo = await latestBlock(); assert.equal( - (await I_PolyToken.balanceOf(account_investor1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), + (await I_PolyToken.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 10500, "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 }); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, new BN(10).pow(new BN(21)), { from: account_investor1 }); // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(new BN(10).pow(new BN(21)), { from: account_investor1 }); - - 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].getRaised.call(POLY)).div(new BN(10).pow(new BN(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(), + (await I_SecurityToken_POLY.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 5000 ); }); it("Verification of the event Token Purchase", async () => { - const log = await promisifyLogWatch(I_CappedSTO_Array_POLY[0].TokenPurchase({ from: blockNo }), 1); + const log = (await I_CappedSTO_Array_POLY[0].getPastEvents('TokenPurchase', {filter: {from: blockNo}}))[0]; 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"); + assert.equal(log.args.amount.div(new BN(10).pow(new BN(18))).toNumber(), 5000, "Wrong No. token get dilivered"); }); - it("Should failed to buy tokens -- because fundraisetype is POLY not ETH", async() => { + it("Should failed to buy tokens -- because fundraisetype is POLY not ETH", async () => { await catchRevert( // Fallback transaction web3.eth.sendTransaction({ from: account_investor1, to: I_CappedSTO_Array_POLY[0].address, gas: 2100000, - value: web3.utils.toWei("2", "ether") + value: new BN(web3.utils.toWei("2", "ether")) }) ); }); - it("Should fail in buying tokens because buying is paused", async() => { + it("Should fail in buying tokens because buying is paused", async () => { await I_CappedSTO_Array_POLY[0].pause({ from: account_issuer }); - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 1000 * Math.pow(10, 18), { from: account_investor1 }); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, new BN(10).pow(new BN(21)), { from: account_investor1 }); // buyTokensWithPoly transaction await catchRevert( - I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { + I_CappedSTO_Array_POLY[0].buyTokensWithPoly(new BN(10).pow(new BN(21)), { from: account_investor1, gas: 6000000 }) @@ -776,7 +752,7 @@ contract("CappedSTO", accounts => { }); it("Should buy the granular unit tokens and charge only required POLY", async () => { - await I_SecurityToken_POLY.changeGranularity(10 ** 22, {from: token_owner}); + await I_SecurityToken_POLY.changeGranularity(new BN(10).pow(new BN(22)), { from: token_owner }); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, P_fromTime, @@ -788,53 +764,56 @@ contract("CappedSTO", accounts => { gas: 500000 } ); - console.log((await I_SecurityToken_POLY.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber()); + console.log((await I_SecurityToken_POLY.balanceOf(account_investor2)).div(new BN(10).pow(new BN(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); + await I_PolyToken.getTokens(new BN(10).pow(new BN(22)), account_investor2); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, new BN(9000).mul(new BN(10).pow(new BN(18))), { from: account_investor2 }); + const initRaised = (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).div(new BN(10).pow(new BN(18))).toNumber(); + tx = await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(new BN(3000).mul(new BN(10).pow(new BN(18))), { from: account_investor2 }); + await I_SecurityToken_POLY.changeGranularity(1, { from: token_owner }); + assert.equal( + (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).div(new BN(10).pow(new BN(18))).toNumber(), + initRaised + 2000 + ); //2000 this call, 1000 earlier + assert.equal((await I_PolyToken.balanceOf(account_investor2)).div(new BN(10).pow(new BN(18))).toNumber(), 8000); assert.equal( - (await I_SecurityToken_POLY.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), + (await I_SecurityToken_POLY.balanceOf(account_investor2)).div(new BN(10).pow(new BN(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(7000 * Math.pow(10, 18), { from: account_investor2 }); + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(new BN(7000).mul(new BN(10).pow(new BN(18))), { from: account_investor2 }); - 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].getRaised.call(POLY)).div(new BN(10).pow(new BN(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(), + (await I_SecurityToken_POLY.balanceOf(account_investor2)).div(new BN(10).pow(new BN(18))).toNumber(), 45000 ); - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 1000 * Math.pow(10, 18), { from: account_investor1 }); - await catchRevert( - I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { from: account_investor1 }) - ); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, new BN(1000).mul(new BN(10).pow(new BN(18))), { from: account_investor1 }); + await catchRevert(I_CappedSTO_Array_POLY[0].buyTokensWithPoly(new BN(1000).mul(new BN(10).pow(new BN(18))), { from: account_investor1 })); }); 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 - await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 1000 * Math.pow(10, 18), { from: account_investor1 }); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, new BN(1000).mul(new BN(10).pow(new BN(18))), { from: account_investor1 }); await catchRevert( - I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { from: account_investor1, gas: 6000000 }) + I_CappedSTO_Array_POLY[0].buyTokensWithPoly(new BN(1000).mul(new BN(10).pow(new BN(18))), { from: account_investor1, gas: 6000000 }) ); }); 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, + (await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toString(), + balanceRaised.toString(), "Somewhere raised money get stolen or sent to wrong wallet" ); }); @@ -842,7 +821,7 @@ 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.getSetupCost.call()).toNumber(), cappedSTOSetupCost); + assert.equal((await I_CappedSTOFactory.getSetupCost.call()).toString(), cappedSTOSetupCost.toString()); 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( @@ -912,11 +891,11 @@ contract("CappedSTO", accounts => { }); 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")); + assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(ETH)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); 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")); + assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).toString(), new BN(web3.utils.toWei("10000", "ether")).toString()); }); it("Should get the investors", async () => { @@ -937,7 +916,7 @@ contract("CappedSTO", accounts => { 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); + startTime_POLY2 = await latestTime() + duration.days(1); endTime_POLY2 = startTime_POLY2 + duration.days(30); await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); @@ -952,42 +931,42 @@ contract("CappedSTO", accounts => { account_fundsReceiver ]); - const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); + const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(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)); + I_CappedSTO_Array_POLY.push(await 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" + (await I_CappedSTO_Array_POLY[1].startTime.call()).toString(), + startTime_POLY2.toString(), + "1STO 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" + (await I_CappedSTO_Array_POLY[1].endTime.call()).toString(), + endTime_POLY2.toString(), + "2STO 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" + (await I_CappedSTO_Array_POLY[1].cap.call()).div(new BN(10).pow(new BN(18))).toString(), + new BN(P_cap).div(new BN(10).pow(new BN(18))).toString(), + "3STO 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].rate.call()).toString(), new BN(P_rate).toString(), "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" + "4STO Configuration doesn't set as expected" ); }); it("Should successfully invest in second STO", async () => { - const polyToInvest = 1000; - const stToReceive = (polyToInvest * P_rate)/Math.pow(10, 18); + const polyToInvest = new BN(1000); + const stToReceive = new BN(polyToInvest.mul(new BN(P_rate).div(new BN(10).pow(new BN(18))))); - await I_PolyToken.getTokens(polyToInvest * Math.pow(10, 18), account_investor3); + await I_PolyToken.getTokens(polyToInvest.mul(new BN(10).pow(new BN(18))), account_investor3); let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, { from: account_issuer, @@ -997,25 +976,25 @@ contract("CappedSTO", accounts => { // 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 }); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[1].address, polyToInvest.mul(new BN(10).pow(new BN(18))), { from: account_investor3 }); // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[1].buyTokensWithPoly(polyToInvest * Math.pow(10, 18), { + await I_CappedSTO_Array_POLY[1].buyTokensWithPoly(polyToInvest.mul(new BN(10).pow(new BN(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 + (await I_CappedSTO_Array_POLY[1].getRaised.call(POLY)).div(new BN(10).pow(new BN(18))).toString(), + polyToInvest.toString() ); 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 + (await I_SecurityToken_POLY.balanceOf(account_investor3)).div(new BN(10).pow(new BN(18))).toString(), + stToReceive.toString() ); - }); + }); }); }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 2e7e6987f..d50620db6 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -7,10 +7,10 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("Checkpoints", accounts => { +contract("Checkpoints", async function(accounts) { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -20,13 +20,13 @@ contract("Checkpoints", accounts => { 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!"; + // investor Details + let fromTime; + let toTime; + let expiryTime; + // Contract Instance Declaration let I_GeneralPermissionManagerFactory; let I_SecurityTokenRegistryProxy; @@ -59,9 +59,12 @@ contract("Checkpoints", accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); before(async () => { + fromTime = await latestTime(); + toTime = await latestTime(); + expiryTime = toTime + duration.days(15); // Accounts setup account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -117,15 +120,14 @@ contract("Checkpoints", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -138,26 +140,25 @@ contract("Checkpoints", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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 ltime = new BN(await latestTime()); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + ltime, + ltime, + ltime.add(new BN(duration.days(10))), false, { from: account_issuer, gas: 6000000 } ); - assert.equal( tx.logs[0].args._investor.toLowerCase(), account_investor1.toLowerCase(), @@ -165,19 +166,19 @@ contract("Checkpoints", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei("10", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("10", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); it("Should Buy some more tokens", async () => { // Add the Investor in to the whitelist - + let ltime = new BN(await latestTime()); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + ltime, + ltime, + ltime.add(new BN(duration.days(10))), false, { from: account_issuer, @@ -192,17 +193,18 @@ contract("Checkpoints", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("10", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("10", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); it("Add a new token holder", async () => { + let ltime = new BN(await latestTime()); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + ltime, + ltime, + ltime.add(new BN(duration.days(10))), false, { from: account_issuer, @@ -218,9 +220,9 @@ contract("Checkpoints", accounts => { // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("10", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("10", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); it("Fuzz test balance checkpoints", async () => { @@ -228,10 +230,10 @@ contract("Checkpoints", accounts => { let cps = []; let ts = []; for (let j = 0; j < 10; j++) { - let balance1 = new BigNumber(await I_SecurityToken.balanceOf(account_investor1)); - let balance2 = new BigNumber(await I_SecurityToken.balanceOf(account_investor2)); - let balance3 = new BigNumber(await I_SecurityToken.balanceOf(account_investor3)); - let totalSupply = new BigNumber(await I_SecurityToken.totalSupply()); + let balance1 = new BN(await I_SecurityToken.balanceOf(account_investor1)); + let balance2 = new BN(await I_SecurityToken.balanceOf(account_investor2)); + let balance3 = new BN(await I_SecurityToken.balanceOf(account_investor3)); + let totalSupply = new BN(await I_SecurityToken.totalSupply()); cps.push([balance1, balance2, balance3]); ts.push(totalSupply); console.log( @@ -266,21 +268,19 @@ contract("Checkpoints", accounts => { } else { receiver = account_investor3; } - let m = Math.random(); - let amount = new BigNumber(await I_SecurityToken.balanceOf(sender)) - .mul(Math.random().toFixed(10)) - .toFixed(0); - if (m > 0.8) { + let m = Math.floor(Math.random() * 10) + 1; + let amount; + if (m > 8) { console.log("Sending full balance"); - amount = new BigNumber(await I_SecurityToken.balanceOf(sender)); + amount = new BN(await I_SecurityToken.balanceOf(sender)); + } else { + amount = new BN(await I_SecurityToken.balanceOf(sender)).mul(new BN(m)).div(new BN(10)); } 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 = new BigNumber(Math.random().toFixed(10)) - .mul(10 ** 17) - .toFixed(0); + let n = new BN(Math.random().toFixed(10)).mul(new BN(10).pow(new BN(17))); let p = Math.random() * 3; let r = Math.random() * 3; let minter; @@ -295,7 +295,7 @@ contract("Checkpoints", accounts => { await I_SecurityToken.mint(minter, n, { from: token_owner }); } if (Math.random() > 0.5) { - let n = new BigNumber(Math.random().toFixed(10)).mul(10 ** 17); + let n = new BN(Math.random().toFixed(10)).mul(new BN(10).pow(new BN(17))); let p = Math.random() * 3; let r = Math.random() * 3; let burner; @@ -306,20 +306,19 @@ contract("Checkpoints", accounts => { } else { burner = account_investor3; } - let burnerBalance = new BigNumber(await I_SecurityToken.balanceOf(burner)); - if (n.gt(burnerBalance.div(2))) { - n = burnerBalance.div(2); + let burnerBalance = new BN(await I_SecurityToken.balanceOf(burner)); + if (n.gt(burnerBalance.div(new BN(2)))) { + n = burnerBalance.div(new BN(2)); } - n = n.toFixed(0); console.log("Burning: " + n.toString() + " from: " + burner); - await I_SecurityToken.forceBurn(burner, n, "", "", { from: token_owner }); + await I_SecurityToken.forceBurn(burner, n, "0x0", "0x0", { from: token_owner }); } console.log("Checking Interim..."); for (let k = 0; k < cps.length; k++) { - let balance1 = new BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); - let balance2 = new BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); - let balance3 = new BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); - let totalSupply = new BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); + let balance1 = new BN(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); + let balance2 = new BN(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); + let balance3 = new BN(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); + let totalSupply = new BN(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])); @@ -332,10 +331,10 @@ contract("Checkpoints", accounts => { } console.log("Checking..."); for (let k = 0; k < cps.length; k++) { - let balance1 = new BigNumber(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); - let balance2 = new BigNumber(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); - let balance3 = new BigNumber(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); - let totalSupply = new BigNumber(await I_SecurityToken.totalSupplyAt(k + 1)); + let balance1 = new BN(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); + let balance2 = new BN(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); + let balance3 = new BN(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); + let totalSupply = new BN(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])); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 2e42fb093..18594249d 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -11,10 +11,10 @@ const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFac const CountTransferManager = artifacts.require("./CountTransferManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("CountTransferManager", accounts => { +contract("CountTransferManager", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -24,11 +24,6 @@ contract("CountTransferManager", accounts => { 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 @@ -70,13 +65,16 @@ contract("CountTransferManager", accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); // CountTransferManager details const holderCount = 2; // Maximum number of token holders let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); + let currentTime; + before(async () => { + currentTime = new BN(await latestTime()); // Accounts setup account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -109,7 +107,7 @@ contract("CountTransferManager", accounts => { // STEP 2: Deploy the CountTransferManager [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 3: Deploy Paid the CountTransferManager - [P_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); + [P_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, new BN(web3.utils.toWei("500", "ether"))); // Printing all the contract addresses console.log(` @@ -138,14 +136,14 @@ contract("CountTransferManager", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -154,13 +152,13 @@ contract("CountTransferManager", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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 I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -168,12 +166,12 @@ contract("CountTransferManager", accounts => { 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 }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_CountTransferManagerFactory.address, bytesSTO, - web3.utils.toWei("500", "ether"), - 0, + new BN(web3.utils.toWei("500", "ether")), + new BN(0), { from: token_owner } ); assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); @@ -182,19 +180,19 @@ contract("CountTransferManager", accounts => { "CountTransferManager", "CountTransferManagerFactory module was not added" ); - P_CountTransferManager = CountTransferManager.at(tx.logs[3].args._module); + P_CountTransferManager = await 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 }); + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, new BN(0), new BN(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); + I_CountTransferManager = await CountTransferManager.at(tx.logs[2].args._module); }); }); @@ -204,9 +202,9 @@ contract("CountTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -224,9 +222,9 @@ contract("CountTransferManager", 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should Buy some more tokens", async () => { @@ -234,9 +232,9 @@ contract("CountTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -251,19 +249,19 @@ contract("CountTransferManager", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("2", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); - it("Should able to buy some more tokens (more than 2 hoders) -- because CountTransferManager is paused", async() => { - await I_CountTransferManager.pause({from: account_issuer }); + it("Should able to buy some more tokens (more than 2 hoders) -- because CountTransferManager is paused", async () => { + await I_CountTransferManager.pause({ from: account_issuer }); let snapId = await takeSnapshot(); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -277,18 +275,18 @@ contract("CountTransferManager", accounts => { "Failed in adding the investor in whitelist" ); - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("3", "ether"), { from: token_owner }) + await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("3", "ether")), { from: token_owner }); await revertToSnapshot(snapId); - }) + }); it("Should fail to buy some more tokens (more than 2 holders)", async () => { - await I_CountTransferManager.unpause({from: account_issuer }); + await I_CountTransferManager.unpause({ from: account_issuer }); // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -302,23 +300,23 @@ contract("CountTransferManager", accounts => { "Failed in adding the investor in whitelist" ); - await catchRevert(I_SecurityToken.mint(account_investor3, web3.utils.toWei("3", "ether"), { from: token_owner })); + await catchRevert(I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("3", "ether")), { from: token_owner })); }); 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 }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("4", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("4", "ether")).toString()); }); 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Should fail in modifying the holder count", async () => { @@ -336,18 +334,18 @@ contract("CountTransferManager", accounts => { 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 }); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("4", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("4", "ether")).toString()); }); it("Should not be able to transfer to a new token holder", async () => { // await I_CountTransferManager.unpause({from: token_owner}); - await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); + await catchRevert(I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); }); it("Should be able to consolidate balances", async () => { - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); }); it("Should get the permission list", async () => { @@ -357,27 +355,26 @@ contract("CountTransferManager", accounts => { 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[2].args._securityTokenAddress); + I_SecurityToken2 = await SecurityToken.at(tx2.logs[2].args._securityTokenAddress); let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; - I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager2 = await GeneralTransferManager.at(moduleData); }); it("add 3 holders to the token", async () => { - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -387,9 +384,9 @@ contract("CountTransferManager", accounts => { await I_GeneralTransferManager2.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -399,9 +396,9 @@ contract("CountTransferManager", accounts => { await I_GeneralTransferManager2.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -411,9 +408,9 @@ contract("CountTransferManager", accounts => { await I_GeneralTransferManager2.modifyWhitelist( account_investor4, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -425,46 +422,46 @@ contract("CountTransferManager", accounts => { 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")); + await I_SecurityToken2.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken2.mint(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken2.mint(account_investor3, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; - I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager2 = await 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 I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); await catchRevert( - I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("500", "ether")), new BN(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 }); + const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, new BN(0), new BN(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})); + I_CountTransferManager2 = await 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 }); + let amount = await I_SecurityToken2.balanceOf(account_investor2); + 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); + assert((await I_SecurityToken2.balanceOf(account_investor4)).toString(), amount.toString(), { from: account_investor2 }); + assert(await I_SecurityToken2.getInvestorCount({ from: account_investor2 }), investorCount); }); }); @@ -496,78 +493,68 @@ contract("CountTransferManager", accounts => { }); }); - describe("Test cases for the ModuleFactory", async() => { - it("Should successfully change the SetupCost -- fail beacuse of bad owner", async() => { + describe("Test cases for the ModuleFactory", async () => { + it("Should successfully change the SetupCost -- fail beacuse of bad owner", async () => { await catchRevert( - I_CountTransferManagerFactory.changeFactorySetupFee(web3.utils.toWei("500"), {from: account_investor3}) + I_CountTransferManagerFactory.changeFactorySetupFee(new BN(web3.utils.toWei("500")), { from: account_investor3 }) ); }); - it("Should successfully change the setupCost", async() => { - await I_CountTransferManagerFactory.changeFactorySetupFee(web3.utils.toWei("800"), { from: account_polymath }); - assert.equal(await I_CountTransferManagerFactory.getSetupCost.call(), web3.utils.toWei("800")); - }) + it("Should successfully change the setupCost", async () => { + await I_CountTransferManagerFactory.changeFactorySetupFee(new BN(web3.utils.toWei("800")), { from: account_polymath }); + assert.equal((await I_CountTransferManagerFactory.getSetupCost.call()).toString(), new BN(web3.utils.toWei("800")).toString()); + }); - it("Should successfully change the usage fee -- fail beacuse of bad owner", async() => { + it("Should successfully change the usage fee -- fail beacuse of bad owner", async () => { await catchRevert( - I_CountTransferManagerFactory.changeFactoryUsageFee(web3.utils.toWei("500"), {from: account_investor3}) + I_CountTransferManagerFactory.changeFactoryUsageFee(new BN(web3.utils.toWei("500")), { from: account_investor3 }) ); }); - it("Should successfully change the usage fee", async() => { - await I_CountTransferManagerFactory.changeFactoryUsageFee(web3.utils.toWei("800"), { from: account_polymath }); - assert.equal(await I_CountTransferManagerFactory.usageCost.call(), web3.utils.toWei("800")); + it("Should successfully change the usage fee", async () => { + await I_CountTransferManagerFactory.changeFactoryUsageFee(new BN(web3.utils.toWei("800")), { from: account_polymath }); + assert.equal((await I_CountTransferManagerFactory.usageCost.call()).toString(), new BN(web3.utils.toWei("800")).toString()); }); - it("Should successfully change the subscription fee -- fail beacuse of bad owner", async() => { + it("Should successfully change the subscription fee -- fail beacuse of bad owner", async () => { await catchRevert( - I_CountTransferManagerFactory.changeFactorySubscriptionFee(web3.utils.toWei("500"), {from: account_investor3}) + I_CountTransferManagerFactory.changeFactorySubscriptionFee(new BN(web3.utils.toWei("500")), { from: account_investor3 }) ); }); - it("Should successfully change the subscription fee", async() => { - await I_CountTransferManagerFactory.changeFactorySubscriptionFee(web3.utils.toWei("800"), { from: account_polymath }); - assert.equal(await I_CountTransferManagerFactory.monthlySubscriptionCost.call(), web3.utils.toWei("800")); + it("Should successfully change the subscription fee", async () => { + await I_CountTransferManagerFactory.changeFactorySubscriptionFee(new BN(web3.utils.toWei("800")), { from: account_polymath }); + assert.equal((await I_CountTransferManagerFactory.monthlySubscriptionCost.call()), new BN(web3.utils.toWei("800")).toString()); }); - it("Should successfully change the version of the factory -- failed because of bad owner", async() => { - await catchRevert( - I_CountTransferManagerFactory.changeVersion("5.0.0", {from: account_investor3}) - ); + it("Should successfully change the version of the factory -- failed because of bad owner", async () => { + await catchRevert(I_CountTransferManagerFactory.changeVersion("5.0.0", { from: account_investor3 })); }); - it("Should successfully change the version of the fatory -- failed because of the 0 string", async() => { - await catchRevert( - I_CountTransferManagerFactory.changeVersion("", {from: account_polymath}) - ); + it("Should successfully change the version of the fatory -- failed because of the 0 string", async () => { + await catchRevert(I_CountTransferManagerFactory.changeVersion("", { from: account_polymath })); }); - it("Should successfully change the version of the fatory", async() => { - await I_CountTransferManagerFactory.changeVersion("5.0.0", {from: account_polymath}); + 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.version.call(), "5.0.0"); }); - }) + }); - describe("Test case for the changeSTVersionBounds", async() => { - it("Should successfully change the version bounds -- failed because of the non permitted bound type", async() => { - await catchRevert( - I_CountTransferManagerFactory.changeSTVersionBounds("middleType", [1,2,3], {from: account_polymath}) - ); - }) + describe("Test case for the changeSTVersionBounds", async () => { + it("Should successfully change the version bounds -- failed because of the non permitted bound type", async () => { + await catchRevert(I_CountTransferManagerFactory.changeSTVersionBounds("middleType", [1, 2, 3], { from: account_polymath })); + }); - it("Should successfully change the version bound --failed because the new version length < 3", async()=> { - await catchRevert( - I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,2], {from: account_polymath}) - ); - }) + it("Should successfully change the version bound --failed because the new version length < 3", async () => { + await catchRevert(I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1, 2], { from: account_polymath })); + }); - it("Should successfully change the version bound", async()=> { - await I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,2,1], {from: account_polymath}); - await I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,4,9], {from: account_polymath}); - await catchRevert( - I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,0,0], {from: account_polymath}) - ); - }) - }) + it("Should successfully change the version bound", async () => { + await I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1, 2, 1], { from: account_polymath }); + await I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1, 4, 9], { from: account_polymath }); + await catchRevert(I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1, new BN(0), 0], { from: account_polymath })); + }); + }); }); }); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 7c9836d42..49472fc7a 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -10,10 +10,10 @@ const ERC20DividendCheckpoint = artifacts.require("./ERC20DividendCheckpoint"); const GeneralPermissionManager = artifacts.require("GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("ERC20DividendCheckpoint", accounts => { +contract("ERC20DividendCheckpoint", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -25,11 +25,6 @@ contract("ERC20DividendCheckpoint", accounts => { let account_manager; 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"; @@ -70,15 +65,18 @@ contract("ERC20DividendCheckpoint", accounts => { const checkpointKey = 4; //Manager details - const managerDetails = "Hello, I am a legit manager"; + const managerDetails = web3.utils.fromAscii("Hello"); // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); + + const one_address = "0x0000000000000000000000000000000000000001"; + const address_zero = "0x0000000000000000000000000000000000000000"; - const one_address = '0x0000000000000000000000000000000000000001'; + let currentTime; before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -109,7 +107,11 @@ contract("ERC20DividendCheckpoint", accounts => { I_STRGetter ] = instances; - [P_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); + [P_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed( + account_polymath, + I_MRProxied, + new BN(web3.utils.toWei("500", "ether")) + ); [I_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed(account_polymath, I_MRProxied, 0); // Printing all the contract addresses @@ -139,15 +141,15 @@ contract("ERC20DividendCheckpoint", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // 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"); @@ -155,12 +157,12 @@ contract("ERC20DividendCheckpoint", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should successfully attach the ERC20DividendCheckpoint with the security token - fail insufficient payment", async () => { await catchRevert( - I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -168,9 +170,9 @@ contract("ERC20DividendCheckpoint", accounts => { 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, { + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); @@ -179,19 +181,19 @@ contract("ERC20DividendCheckpoint", accounts => { "ERC20DividendCheckpoint", "ERC20DividendCheckpoint module was not added" ); - P_ERC20DividendCheckpoint = ERC20DividendCheckpoint.at(tx.logs[3].args._module); + P_ERC20DividendCheckpoint = await 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 }); + const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "0x0", new BN(0), new BN(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); + I_ERC20DividendCheckpoint = await ERC20DividendCheckpoint.at(tx.logs[2].args._module); }); }); @@ -201,9 +203,9 @@ contract("ERC20DividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(30), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(30))), true, { from: account_issuer, @@ -221,9 +223,9 @@ contract("ERC20DividendCheckpoint", 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Buy some tokens for account_investor2 (2 ETH)", async () => { @@ -231,9 +233,9 @@ contract("ERC20DividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(30), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(30))), true, { from: account_issuer, @@ -248,21 +250,21 @@ contract("ERC20DividendCheckpoint", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("2", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Should fail in creating the dividend - incorrect allowance", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei("1.5", "ether"), token_owner); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1.5", "ether")), token_owner); await catchRevert( I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: token_owner } ) @@ -270,15 +272,15 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Should fail in creating the dividend - maturity > expiry", async () => { - 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 }); + let maturity = await latestTime(); + let expiry = await latestTime() - duration.days(10); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, new BN(web3.utils.toWei("1.5", "ether")), { from: token_owner }); await catchRevert( I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: token_owner } ) @@ -286,14 +288,14 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Should fail in creating the dividend - now > expiry", async () => { - let maturity = latestTime() - duration.days(2); - let expiry = latestTime() - duration.days(1); + let maturity = await latestTime() - duration.days(2); + let expiry = await latestTime() - duration.days(1); await catchRevert( I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: token_owner } ) @@ -301,32 +303,32 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Should fail in creating the dividend - bad token", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); await catchRevert( - I_ERC20DividendCheckpoint.createDividend(maturity, expiry, 0, web3.utils.toWei("1.5", "ether"), dividendName, { + I_ERC20DividendCheckpoint.createDividend(maturity, expiry, address_zero, new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: token_owner }) ); }); it("Should fail in creating the dividend - amount is 0", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); await catchRevert( - I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, 0, dividendName, { from: token_owner }) + I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, new BN(0), dividendName, { from: token_owner }) ); }); it("Create new dividend of POLY tokens", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let tx = await I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: token_owner } ); @@ -335,35 +337,35 @@ contract("ERC20DividendCheckpoint", accounts => { }); 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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("3", "ether")).toString()); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails maturity in the future", async () => { - await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, { from: token_owner })); + await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: token_owner })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails not owner", async () => { // Increase time by 2 day await increaseTime(duration.days(2)); - await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, { from: account_temp })); + await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: account_temp })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails wrong index", async () => { - await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, { from: token_owner })); + await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(2, new BN(0), 10, { from: token_owner })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async () => { - let investor1Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); - await I_ERC20DividendCheckpoint.pushDividendPayment(0, 0, 10, { from: token_owner, gas: 5000000 }); - let investor1BalanceAfter = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2BalanceAfter = new 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")); + let investor1Balance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = new BN(await I_PolyToken.balanceOf(account_investor2)); + await I_ERC20DividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: token_owner, gas: 5000000 }); + let investor1BalanceAfter = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter = new BN(await I_PolyToken.balanceOf(account_investor2)); + assert.equal(investor1BalanceAfter.sub(investor1Balance).toString(), new BN(web3.utils.toWei("0.5", "ether")).toString()); + assert.equal(investor2BalanceAfter.sub(investor2Balance).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); //Check fully claimed - assert.equal((await I_ERC20DividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei("1.5", "ether")); + assert.equal((await I_ERC20DividendCheckpoint.dividends(0))[5].toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); }); it("Buy some tokens for account_temp (1 ETH)", async () => { @@ -371,9 +373,9 @@ contract("ERC20DividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_temp, - latestTime(), - latestTime(), - latestTime() + duration.days(20), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(20))), true, { from: account_issuer, @@ -384,33 +386,33 @@ contract("ERC20DividendCheckpoint", accounts => { 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 }); + await I_SecurityToken.mint(account_temp, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_temp)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_temp)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); 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 maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1.5", "ether")), token_owner); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, new BN(web3.utils.toWei("1.5", "ether")), { from: token_owner }); await catchRevert( - I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, web3.utils.toWei("1.5", "ether"), "", { + I_ERC20DividendCheckpoint.createDividend(maturity, expiry, I_PolyToken.address, new BN(web3.utils.toWei("1.5", "ether")), "0x0", { from: token_owner }) ); }); 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); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1.5", "ether")), token_owner); // transfer approved in above test let tx = await I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: token_owner } ); @@ -419,12 +421,12 @@ contract("ERC20DividendCheckpoint", accounts => { it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint - fails past expiry", async () => { await increaseTime(duration.days(12)); - await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(1, 0, 10, { from: token_owner })); + await catchRevert(I_ERC20DividendCheckpoint.pushDividendPayment(1, new BN(0), 10, { from: token_owner })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoin - fails already reclaimed", async () => { 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")); + assert.equal(tx.logs[0].args._claimedAmount.toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); await catchRevert(I_ERC20DividendCheckpoint.reclaimDividend(1, { from: token_owner, gas: 500000 })); }); @@ -433,9 +435,9 @@ contract("ERC20DividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(100000))), true, { from: account_issuer, @@ -450,17 +452,17 @@ contract("ERC20DividendCheckpoint", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("7", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("7", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("7", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("Should allow to exclude same number of address as EXCLUDED_ADDRESS_LIMIT", async () => { let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); - limit = limit.toNumber(); + limit = limit.toNumber() + 42; let addresses = []; addresses.push(account_temp); - while (--limit) addresses.push(limit); + while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); await I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner }); let excluded = await I_ERC20DividendCheckpoint.getDefaultExcluded(); assert.equal(excluded[0], account_temp); @@ -476,7 +478,7 @@ contract("ERC20DividendCheckpoint", accounts => { it("Should not allow to exclude 0x0 address", async () => { let addresses = []; addresses.push(account_investor3); - addresses.push(0); + addresses.push(address_zero); await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner })); }); @@ -488,23 +490,23 @@ contract("ERC20DividendCheckpoint", accounts => { it("Should not allow to exclude more address than EXCLUDED_ADDRESS_LIMIT", async () => { let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); - limit = limit.toNumber(); + limit = limit.toNumber() + 42; let addresses = []; addresses.push(account_temp); - while (limit--) addresses.push(limit); + while (limit-- > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { 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 maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("11", "ether")), token_owner); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, new BN(web3.utils.toWei("11", "ether")), { from: token_owner }); let tx = await I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("10", "ether"), + new BN(web3.utils.toWei("10", "ether")), dividendName, { from: token_owner } ); @@ -517,16 +519,16 @@ contract("ERC20DividendCheckpoint", accounts => { it("should investor 3 claims dividend", async () => { console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); - let investor1Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let investor1Balance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = new BN(await I_PolyToken.balanceOf(account_investor3)); await I_ERC20DividendCheckpoint.pullDividendPayment(2, { from: account_investor3, 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 investor1BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = new BN(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")); + assert.equal(investor3BalanceAfter1.sub(investor3Balance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("should investor 3 claims dividend - fails already claimed", async () => { @@ -534,22 +536,21 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("should issuer pushes remain", async () => { - console.log((await I_ERC20DividendCheckpoint.dividends(2))[5].toNumber()); - 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 investorTempBalanceAfter1 = new BigNumber(await I_PolyToken.balanceOf(account_temp)); - await I_ERC20DividendCheckpoint.pushDividendPayment(2, 0, 10, { 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)); - let investorTempBalanceAfter2 = new BigNumber(await I_PolyToken.balanceOf(account_temp)); + let investor1BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor3)); + let investorTempBalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_temp)); + await I_ERC20DividendCheckpoint.pushDividendPayment(2, new BN(0), 10, { from: token_owner }); + let investor1BalanceAfter2 = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter2 = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter2 = new BN(await I_PolyToken.balanceOf(account_investor3)); + let investorTempBalanceAfter2 = new BN(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(investor2BalanceAfter2.sub(investor2BalanceAfter1).toString(), new BN(web3.utils.toWei("3", "ether")).toString()); 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")); + assert.equal((await I_ERC20DividendCheckpoint.dividends(2))[5].toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); it("Delete global exclusion list", async () => { @@ -557,26 +558,26 @@ contract("ERC20DividendCheckpoint", accounts => { }); 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")); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_temp)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Create another new dividend with explicit checkpoint - fails bad allowance", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); + let maturity = await latestTime(); + let expiry = await 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); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("20", "ether")), token_owner); await catchRevert( I_ERC20DividendCheckpoint.createDividendWithCheckpoint( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("20", "ether"), + new BN(web3.utils.toWei("20", "ether")), 4, dividendName, { from: token_owner } @@ -587,15 +588,15 @@ contract("ERC20DividendCheckpoint", accounts => { it("Create another new dividend with explicit - fails maturity > expiry", async () => { console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei("20", "ether"), { from: token_owner }); + let maturity = await latestTime(); + let expiry = await latestTime() - duration.days(10); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, new BN(web3.utils.toWei("20", "ether")), { from: token_owner }); await catchRevert( I_ERC20DividendCheckpoint.createDividendWithCheckpoint( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("20", "ether"), + new BN(web3.utils.toWei("20", "ether")), 4, dividendName, { from: token_owner } @@ -606,14 +607,14 @@ contract("ERC20DividendCheckpoint", accounts => { it("Create another new dividend with explicit - fails now > expiry", async () => { console.log((await I_SecurityToken.currentCheckpointId()).toNumber()); - let maturity = latestTime() - duration.days(5); - let expiry = latestTime() - duration.days(2); + let maturity = await latestTime() - duration.days(5); + let expiry = await latestTime() - duration.days(2); await catchRevert( I_ERC20DividendCheckpoint.createDividendWithCheckpoint( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("20", "ether"), + new BN(web3.utils.toWei("20", "ether")), 4, dividendName, { from: token_owner } @@ -622,14 +623,14 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Create another new dividend with explicit - fails bad checkpoint", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(2); await catchRevert( I_ERC20DividendCheckpoint.createDividendWithCheckpoint( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("20", "ether"), + new BN(web3.utils.toWei("20", "ether")), 5, dividendName, { from: token_owner } @@ -638,46 +639,41 @@ contract("ERC20DividendCheckpoint", accounts => { }); 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 } - ); + await I_ERC20DividendCheckpoint.setWithholding([account_temp, account_investor2], [new BN(20).mul(new BN(10).pow(new BN(16))), new BN(10).mul(new BN(10).pow(new BN(16)))], { + from: token_owner + }); }); it("Should not allow mismatching input lengths", async () => { await catchRevert( - I_ERC20DividendCheckpoint.setWithholding([account_temp], [BigNumber(20 * 10 ** 16), BigNumber(10 * 10 ** 16)], { + I_ERC20DividendCheckpoint.setWithholding([account_temp], [new BN(20).mul(new BN(10).pow(new BN(16))), new BN(10).mul(new BN(10).pow(new BN(16)))], { from: token_owner }) ); }); it("Should not allow withholding greater than limit", async () => { - await catchRevert(I_ERC20DividendCheckpoint.setWithholding([account_temp], [BigNumber(20 * 10 ** 26)], { from: token_owner })); - await catchRevert( - I_ERC20DividendCheckpoint.setWithholdingFixed([account_temp], BigNumber(20 * 10 ** 26), { from: token_owner }), - "" - ); + await catchRevert(I_ERC20DividendCheckpoint.setWithholding([account_temp], [new BN(20).mul(new BN(10).pow(new BN(26)))], { from: token_owner })); + await catchRevert(I_ERC20DividendCheckpoint.setWithholdingFixed([account_temp], new BN(20).mul(new BN(10).pow(new BN(26))), { from: token_owner }), ""); }); it("Should not create dividend with more exclusions than limit", 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 maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("11", "ether")), token_owner); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, new BN(web3.utils.toWei("11", "ether")), { from: token_owner }); let limit = await I_ERC20DividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); - limit = limit.toNumber(); + limit = limit.toNumber() + 42; let addresses = []; addresses.push(account_temp); addresses.push(token_owner); - while (--limit) addresses.push(limit); + while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); await catchRevert( I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("10", "ether"), + new BN(web3.utils.toWei("10", "ether")), 4, addresses, dividendName, @@ -687,15 +683,15 @@ contract("ERC20DividendCheckpoint", accounts => { }); 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); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("11", "ether")), token_owner); //token transfer approved in above test let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("10", "ether"), + new BN(web3.utils.toWei("10", "ether")), 4, [account_investor1], dividendName, @@ -705,37 +701,41 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Should not create new dividend with duplicate exclusion", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei("11", "ether"), token_owner); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("11", "ether")), token_owner); //token transfer approved in above test - await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( - maturity, - expiry, - I_PolyToken.address, - web3.utils.toWei("10", "ether"), - 4, - [account_investor1, account_investor1], - dividendName, - { from: token_owner } - )); + await catchRevert( + I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( + maturity, + expiry, + I_PolyToken.address, + new BN(web3.utils.toWei("10", "ether")), + 4, + [account_investor1, account_investor1], + dividendName, + { from: token_owner } + ) + ); }); it("Should not create new dividend with 0x0 address in exclusion", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); - await I_PolyToken.getTokens(web3.utils.toWei("11", "ether"), token_owner); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("11", "ether")), token_owner); //token transfer approved in above test - await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( - maturity, - expiry, - I_PolyToken.address, - web3.utils.toWei("10", "ether"), - 4, - [0], - dividendName, - { from: token_owner } - )); + await catchRevert( + I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( + maturity, + expiry, + I_PolyToken.address, + new BN(web3.utils.toWei("10", "ether")), + 4, + [address_zero], + dividendName, + { from: token_owner } + ) + ); }); it("Should not allow excluded to pull Dividend Payment", async () => { @@ -769,48 +769,48 @@ contract("ERC20DividendCheckpoint", accounts => { 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")); + assert.equal(dividendAmount1[0].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + assert.equal(dividendAmount2[0].toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + assert.equal(dividendAmount3[0].toString(), new BN(web3.utils.toWei("7", "ether")).toString()); + assert.equal(dividendAmount_temp[0].toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal(dividendAmount1[1].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + assert.equal(dividendAmount2[1].toString(), new BN(web3.utils.toWei("0.2", "ether")).toString()); + assert.equal(dividendAmount3[1].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + assert.equal(dividendAmount_temp[1].toString(), new BN(web3.utils.toWei("0.2", "ether")).toString()); }); 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)); - let investor3Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); - let tempBalance = new BigNumber(await web3.eth.getBalance(account_temp)); + let investor1Balance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = new BN(await I_PolyToken.balanceOf(account_investor3)); + let tempBalance = new BN(await web3.eth.getBalance(account_temp)); 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)); + let investor1BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor3)); + let tempBalanceAfter1 = new BN(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(investor2BalanceAfter1.sub(investor2Balance).toString(), new BN(web3.utils.toWei("1.8", "ether")).toString()); 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 = 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 I_PolyToken.balanceOf(account_temp)); + let investor1BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_investor3)); + let tempBalanceAfter1 = new BN(await I_PolyToken.balanceOf(account_temp)); await I_ERC20DividendCheckpoint.pushDividendPaymentToAddresses(3, [account_temp, account_investor1], { 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)); - let tempBalanceAfter2 = new BigNumber(await I_PolyToken.balanceOf(account_temp)); + let investor1BalanceAfter2 = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2BalanceAfter2 = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3BalanceAfter2 = new BN(await I_PolyToken.balanceOf(account_investor3)); + let tempBalanceAfter2 = new BN(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")); + assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toString(), new BN(web3.utils.toWei("0.8", "ether")).toString()); //Check fully claimed - assert.equal((await I_ERC20DividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei("3", "ether")); + assert.equal((await I_ERC20DividendCheckpoint.dividends(3))[5].toString(), new BN(web3.utils.toWei("3", "ether")).toString()); }); it("should calculate dividend after the push dividend payment", async () => { @@ -825,10 +825,10 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("Issuer reclaims withholding tax", async () => { - let issuerBalance = new BigNumber(await I_PolyToken.balanceOf(token_owner)); + let issuerBalance = new BN(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)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.4", "ether")); + let issuerBalanceAfter = new BN(await I_PolyToken.balanceOf(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0.4", "ether")).toString()); }); it("Issuer unable to reclaim dividend (expiry not passed)", async () => { @@ -845,10 +845,10 @@ 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 BN(await I_PolyToken.balanceOf(token_owner)); await I_ERC20DividendCheckpoint.reclaimDividend(3, { from: token_owner, gasPrice: 0 }); - let tokenOwnerAfter = new BigNumber(await I_PolyToken.balanceOf(token_owner)); - assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei("7", "ether")); + let tokenOwnerAfter = new BN(await I_PolyToken.balanceOf(token_owner)); + assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("Issuer is unable to reclaim already reclaimed dividend", async () => { @@ -881,7 +881,7 @@ contract("ERC20DividendCheckpoint", accounts => { it("should registr a delegate", async () => { [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); - let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", new BN(0), new BN(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, ""), @@ -889,78 +889,73 @@ contract("ERC20DividendCheckpoint", accounts => { "GeneralPermissionManagerFactory module was not added" ); I_GeneralPermissionManager = await GeneralPermissionManager.at(tx.logs[2].args._module); - tx = await I_GeneralPermissionManager.addDelegate(account_manager, managerDetails, { from: token_owner}); + tx = await I_GeneralPermissionManager.addDelegate(account_manager, managerDetails, { from: token_owner }); assert.equal(tx.logs[0].args._delegate, account_manager); }); it("should not allow manager without permission to set default excluded", async () => { - await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded( - [0], - { from: account_manager } - )); + await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded([address_zero], { from: account_manager })); }); it("should not allow manager without permission to set withholding", async () => { - await catchRevert(I_ERC20DividendCheckpoint.setWithholding( - [0], - [0], - { from: account_manager } - )); + await catchRevert(I_ERC20DividendCheckpoint.setWithholding([address_zero], [new BN(0)], { from: account_manager })); }); it("should not allow manager without permission to set withholding fixed", async () => { - await catchRevert(I_ERC20DividendCheckpoint.setWithholdingFixed( - [0], - 0, - { from: account_manager } - )); + await catchRevert(I_ERC20DividendCheckpoint.setWithholdingFixed([address_zero], new BN(0), { from: account_manager })); }); it("should not allow manager without permission to create dividend", async () => { - await I_PolyToken.transfer(account_manager, web3.utils.toWei("100", "ether"), { from: token_owner }); - await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, web3.utils.toWei("100", "ether"), { from: account_manager }); - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + await I_PolyToken.transfer(account_manager, new BN(web3.utils.toWei("100", "ether")), { from: token_owner }); + await I_PolyToken.approve(I_ERC20DividendCheckpoint.address, new BN(web3.utils.toWei("100", "ether")), { from: account_manager }); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); - await catchRevert(I_ERC20DividendCheckpoint.createDividend( - maturity, - expiry, - I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), - dividendName, - { from: account_manager } - )); + await catchRevert( + I_ERC20DividendCheckpoint.createDividend( + maturity, + expiry, + I_PolyToken.address, + new BN(web3.utils.toWei("1.5", "ether")), + dividendName, + { from: account_manager } + ) + ); }); it("should not allow manager without permission to create dividend with checkpoint", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); - await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpoint( - maturity, - expiry, - I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), - checkpointID.toNumber(), - dividendName, - { from: account_manager } - )); + await catchRevert( + I_ERC20DividendCheckpoint.createDividendWithCheckpoint( + maturity, + expiry, + I_PolyToken.address, + new BN(web3.utils.toWei("1.5", "ether")), + checkpointID.toNumber(), + dividendName, + { from: account_manager } + ) + ); }); it("should not allow manager without permission to create dividend with exclusion", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let exclusions = [1]; - await catchRevert(I_ERC20DividendCheckpoint.createDividendWithExclusions( - maturity, - expiry, - I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), - exclusions, - dividendName, - { from: account_manager } - )); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; + await catchRevert( + I_ERC20DividendCheckpoint.createDividendWithExclusions( + maturity, + expiry, + I_PolyToken.address, + new BN(web3.utils.toWei("1.5", "ether")), + exclusions, + dividendName, + { from: account_manager } + ) + ); }); it("should not allow manager without permission to create checkpoint", async () => { @@ -968,76 +963,59 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("should not allow manager without permission to create dividend with checkpoint and exclusion", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let exclusions = [1]; + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); - await catchRevert(I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( - maturity, - expiry, - I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), - checkpointID.toNumber(), - exclusions, - dividendName, - { from: account_manager } - )); + await catchRevert( + I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( + maturity, + expiry, + I_PolyToken.address, + new BN(web3.utils.toWei("1.5", "ether")), + checkpointID.toNumber(), + exclusions, + dividendName, + { from: account_manager } + ) + ); }); it("should give permission to manager", async () => { - await I_GeneralPermissionManager.changePermission( - account_manager, - I_ERC20DividendCheckpoint.address, - "CHECKPOINT", - true, - { from: token_owner } - ); - let tx = await I_GeneralPermissionManager.changePermission( - account_manager, - I_ERC20DividendCheckpoint.address, - "MANAGE", - true, - { from: token_owner } - ); + await I_GeneralPermissionManager.changePermission(account_manager, I_ERC20DividendCheckpoint.address, web3.utils.fromAscii("CHECKPOINT"), true, { + from: token_owner + }); + let tx = await I_GeneralPermissionManager.changePermission(account_manager, I_ERC20DividendCheckpoint.address, web3.utils.fromAscii("MANAGE"), true, { + from: token_owner + }); assert.equal(tx.logs[0].args._delegate, account_manager); }); it("should allow manager with permission to set default excluded", async () => { - let tx = await I_ERC20DividendCheckpoint.setDefaultExcluded( - [1], - { from: account_manager } - ); + let tx = await I_ERC20DividendCheckpoint.setDefaultExcluded([one_address], { from: account_manager }); assert.equal(tx.logs[0].args._excluded[0], one_address); }); it("should allow manager with permission to set withholding", async () => { - let tx = await I_ERC20DividendCheckpoint.setWithholding( - [0], - [0], - { from: account_manager } - ); + let tx = await I_ERC20DividendCheckpoint.setWithholding([one_address], [new BN(0)], { from: account_manager }); assert.equal(tx.logs[0].args._withholding[0], 0); }); it("should allow manager withpermission to set withholding fixed", async () => { - let tx = await I_ERC20DividendCheckpoint.setWithholdingFixed( - [0], - 0, - { from: account_manager } - ); + let tx = await I_ERC20DividendCheckpoint.setWithholdingFixed([one_address], new BN(0), { from: account_manager }); assert.equal(tx.logs[0].args._withholding, 0); }); it("should allow manager with permission to create dividend", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let tx = await I_ERC20DividendCheckpoint.createDividend( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), dividendName, { from: account_manager } ); @@ -1045,15 +1023,15 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("should allow manager with permission to create dividend with checkpoint", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpoint( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), checkpointID.toNumber(), dividendName, { from: account_manager } @@ -1062,14 +1040,14 @@ 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 maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; let tx = await I_ERC20DividendCheckpoint.createDividendWithExclusions( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), exclusions, dividendName, { from: account_manager } @@ -1078,16 +1056,16 @@ contract("ERC20DividendCheckpoint", accounts => { }); it("should allow manager with permission to create dividend with checkpoint and exclusion", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let exclusions = [1]; + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); let tx = await I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, expiry, I_PolyToken.address, - web3.utils.toWei("1.5", "ether"), + new BN(web3.utils.toWei("1.5", "ether")), checkpointID.toNumber(), exclusions, dividendName, diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 25bacb792..8d9582283 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -11,10 +11,10 @@ const EtherDividendCheckpoint = artifacts.require("./EtherDividendCheckpoint"); const GeneralPermissionManager = artifacts.require("GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("EtherDividendCheckpoint", accounts => { +contract("EtherDividendCheckpoint", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -26,13 +26,10 @@ contract("EtherDividendCheckpoint", accounts => { let account_manager; 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"; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // Contract Instance Declaration let I_SecurityTokenRegistryProxy; @@ -62,7 +59,7 @@ contract("EtherDividendCheckpoint", accounts => { const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; - const managerDetails = "Hello, I am a legit manager"; + const managerDetails = web3.utils.fromAscii("Hello"); let snapId; // Module key const delegateManagerKey = 1; @@ -71,10 +68,12 @@ contract("EtherDividendCheckpoint", accounts => { const checkpointKey = 4; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); + + let currentTime; before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -136,15 +135,15 @@ contract("EtherDividendCheckpoint", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -153,13 +152,13 @@ contract("EtherDividendCheckpoint", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -167,8 +166,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, { + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); @@ -177,19 +176,19 @@ contract("EtherDividendCheckpoint", accounts => { "EtherDividendCheckpoint", "EtherDividendCheckpoint module was not added" ); - P_EtherDividendCheckpoint = EtherDividendCheckpoint.at(tx.logs[3].args._module); + P_EtherDividendCheckpoint = await 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 }); + const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "0x0", new BN(0), new BN(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); + I_EtherDividendCheckpoint = await EtherDividendCheckpoint.at(tx.logs[2].args._module); }); }); @@ -199,9 +198,9 @@ contract("EtherDividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(30), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(300000))), true, { from: account_issuer, @@ -219,9 +218,9 @@ contract("EtherDividendCheckpoint", 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Buy some tokens for account_investor2 (2 ETH)", async () => { @@ -229,9 +228,9 @@ contract("EtherDividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(30), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(3000000))), true, { from: account_issuer, @@ -246,95 +245,95 @@ contract("EtherDividendCheckpoint", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("2", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Should fail in creating the dividend", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); await catchRevert(I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { from: token_owner })); }); it("Should fail in creating the dividend", async () => { - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() - duration.days(10); await catchRevert( I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { from: token_owner, - value: web3.utils.toWei("1.5", "ether") + value: new BN(web3.utils.toWei("1.5", "ether")) }) ); }); it("Should fail in creating the dividend", async () => { - let maturity = latestTime() - duration.days(2); - let expiry = latestTime() - duration.days(1); + let maturity = await latestTime() - duration.days(2); + let expiry = await latestTime() - duration.days(1); await catchRevert( I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { from: token_owner, - value: web3.utils.toWei("1.5", "ether") + value: new BN(web3.utils.toWei("1.5", "ether")) }) ); }); it("Set withholding tax of 20% on investor 2", async () => { - await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], BigNumber(20 * 10 ** 16), { from: token_owner }); + await I_EtherDividendCheckpoint.setWithholdingFixed([account_investor2], new BN(web3.utils.toWei("0.2", "ether")), { from: token_owner }); }); it("Should fail in creating the dividend", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); await catchRevert( - I_EtherDividendCheckpoint.createDividend(maturity, expiry, "", { + I_EtherDividendCheckpoint.createDividend(maturity, expiry, "0x0", { from: token_owner, - value: web3.utils.toWei("1.5", "ether") + value: new BN(web3.utils.toWei("1.5", "ether")) }) ); }); it("Create new dividend", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { from: token_owner, - value: web3.utils.toWei("1.5", "ether") + value: new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("3", "ether")).toString()); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async () => { - await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, { from: token_owner })); + await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: token_owner })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async () => { // Increase time by 2 day await increaseTime(duration.days(2)); - await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, { from: account_temp })); + await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: account_temp })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async () => { - await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(2, 0, 10, { from: token_owner })); + await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(2, new BN(0), 10, { from: token_owner })); }); it("Issuer pushes dividends iterating over account holders - dividends proportional to checkpoint", async () => { - let investor1Balance = new BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2Balance = new BigNumber(await web3.eth.getBalance(account_investor2)); - await I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, { from: token_owner }); - let investor1BalanceAfter = new BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter = new 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")); + let investor1Balance = new BN(await web3.eth.getBalance(account_investor1)); + let investor2Balance = new BN(await web3.eth.getBalance(account_investor2)); + await I_EtherDividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: token_owner }); + let investor1BalanceAfter = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter = new BN(await web3.eth.getBalance(account_investor2)); + assert.equal(investor1BalanceAfter.sub(investor1Balance).toString(), new BN(web3.utils.toWei("0.5", "ether")).toString()); + assert.equal(investor2BalanceAfter.sub(investor2Balance).toString(), new BN(web3.utils.toWei("0.8", "ether")).toString()); //Check fully claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(0))[5].toNumber(), web3.utils.toWei("1.5", "ether")); + assert.equal((await I_EtherDividendCheckpoint.dividends(0))[5].toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); }); it("Should not allow reclaiming withholding tax with incorrect index", async () => { @@ -345,17 +344,17 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Issuer reclaims withholding tax", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); await I_EtherDividendCheckpoint.withdrawWithholding(0, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.2", "ether")); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0.2", "ether")).toString()); }); it("No more withholding tax to withdraw", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); await I_EtherDividendCheckpoint.withdrawWithholding(0, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0", "ether")); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); it("Buy some tokens for account_temp (1 ETH)", async () => { @@ -363,9 +362,9 @@ contract("EtherDividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_temp, - latestTime(), - latestTime(), - latestTime() + duration.days(20), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(200000))), true, { from: account_issuer, @@ -376,37 +375,37 @@ contract("EtherDividendCheckpoint", accounts => { 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 }); + await I_SecurityToken.mint(account_temp, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_temp)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_temp)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Create new dividend", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { from: token_owner, - value: web3.utils.toWei("1.5", "ether") + value: new BN(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 () => { await increaseTime(duration.days(12)); - await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(0, 0, 10, { from: token_owner })); + await catchRevert(I_EtherDividendCheckpoint.pushDividendPayment(0, new BN(0), 10, { from: token_owner })); }); it("Issuer reclaims dividend", async () => { 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")); + assert.equal(tx.logs[0].args._claimedAmount.toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); await catchRevert(I_EtherDividendCheckpoint.reclaimDividend(1, { from: token_owner, gas: 500000 })); }); it("Still no more withholding tax to withdraw", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); await I_EtherDividendCheckpoint.withdrawWithholding(0, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0", "ether")); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); it("Buy some tokens for account_investor3 (7 ETH)", async () => { @@ -414,9 +413,9 @@ contract("EtherDividendCheckpoint", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10000))), true, { from: account_issuer, @@ -431,46 +430,46 @@ contract("EtherDividendCheckpoint", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei("7", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("7", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("7", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("Create another new dividend", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { from: token_owner, - value: web3.utils.toWei("11", "ether") + value: new BN(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 investor1Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let investor1Balance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = new BN(await I_PolyToken.balanceOf(account_investor3)); await catchRevert(I_EtherDividendCheckpoint.pullDividendPayment(5, { from: account_investor3, gasPrice: 0 })); }); it("Should investor 3 claims dividend", async () => { - let investor1Balance = new BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2Balance = new BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3Balance = new BigNumber(await web3.eth.getBalance(account_investor3)); + let investor1Balance = new BN(await web3.eth.getBalance(account_investor1)); + let investor2Balance = new BN(await web3.eth.getBalance(account_investor2)); + let investor3Balance = new BN(await web3.eth.getBalance(account_investor3)); await I_EtherDividendCheckpoint.pullDividendPayment(2, { from: account_investor3, gasPrice: 0 }); - 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)); + let investor1BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = new BN(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")); + assert.equal(investor3BalanceAfter1.sub(investor3Balance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("Still no more withholding tax to withdraw", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); await I_EtherDividendCheckpoint.withdrawWithholding(0, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0", "ether")); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); it("should investor 3 claims dividend", async () => { @@ -478,37 +477,37 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Issuer pushes remainder", async () => { - 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 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)); + let investor1BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor3)); + await I_EtherDividendCheckpoint.pushDividendPayment(2, new BN(0), 10, { from: token_owner }); + let investor1BalanceAfter2 = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter2 = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter2 = new BN(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).toString(), new BN(web3.utils.toWei("2.4", "ether")).toString()); assert.equal(investor3BalanceAfter2.sub(investor3BalanceAfter1).toNumber(), 0); //Check fully claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toNumber(), web3.utils.toWei("11", "ether")); + assert.equal((await I_EtherDividendCheckpoint.dividends(2))[5].toString(), new BN(web3.utils.toWei("11", "ether")).toString()); }); it("Issuer withdraws new withholding tax", async () => { - let issuerBalance = new BigNumber(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); await I_EtherDividendCheckpoint.withdrawWithholding(2, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(issuerBalanceAfter.sub(issuerBalance).toNumber(), web3.utils.toWei("0.6", "ether")); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0.6", "ether")).toString()); }); 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")); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("Create another new dividend with no value - fails", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(2); let tx = await I_SecurityToken.createCheckpoint({ from: token_owner }); await catchRevert( I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, { from: token_owner, value: 0 }) @@ -516,60 +515,60 @@ contract("EtherDividendCheckpoint", accounts => { }); it("Create another new dividend with explicit", async () => { - let maturity = latestTime(); - let expiry = latestTime() - duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() - duration.days(10); await catchRevert( I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, { from: token_owner, - value: web3.utils.toWei("11", "ether") + value: new BN(web3.utils.toWei("11", "ether")) }) ); }); it("Create another new dividend with bad expirty - fails", async () => { - let maturity = latestTime() - duration.days(5); - let expiry = latestTime() - duration.days(2); + let maturity = await latestTime() - duration.days(5); + let expiry = await latestTime() - duration.days(2); await catchRevert( I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 4, dividendName, { from: token_owner, - value: web3.utils.toWei("11", "ether") + value: new BN(web3.utils.toWei("11", "ether")) }) ); }); it("Create another new dividend with bad checkpoint in the future - fails", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(2); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(2); await catchRevert( I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, 5, dividendName, { from: token_owner, - value: web3.utils.toWei("11", "ether") + value: new BN(web3.utils.toWei("11", "ether")) }) ); }); it("Should not create dividend with more exclusions than limit", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); await I_SecurityToken.createCheckpoint({ from: token_owner }); let limit = await I_EtherDividendCheckpoint.EXCLUDED_ADDRESS_LIMIT(); - limit = limit.toNumber(); + limit = limit.toNumber() + 42; let addresses = []; addresses.push(account_temp); addresses.push(token_owner); - while (--limit) addresses.push(limit); + while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); await catchRevert( I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, addresses, dividendName, { from: token_owner, - value: web3.utils.toWei("10", "ether") + value: new BN(web3.utils.toWei("10", "ether")) }), "tx -> failed because too many address excluded" ); }); it("Create another new dividend with explicit checkpoint and excluding account_investor1", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); //checkpoint created in above test let tx = await I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, @@ -577,43 +576,43 @@ contract("EtherDividendCheckpoint", accounts => { 4, [account_investor1], dividendName, - { from: token_owner, value: web3.utils.toWei("10", "ether") } + { from: token_owner, value: new BN(web3.utils.toWei("10", "ether")) } ); 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 () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); //checkpoint created in above test - await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( - maturity, - expiry, - 4, - [account_investor1, account_investor1], - dividendName, - { from: token_owner, value: web3.utils.toWei("10", "ether") } - )); + await catchRevert( + I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( + maturity, + expiry, + 4, + [account_investor1, account_investor1], + dividendName, + { from: token_owner, value: new BN(web3.utils.toWei("10", "ether")) } + ) + ); }); it("Should not create new dividend with 0x0 address in exclusion", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); //checkpoint created in above test - await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( - maturity, - expiry, - 4, - [0], - dividendName, - { from: token_owner, value: web3.utils.toWei("10", "ether") } - )); + await catchRevert( + I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, [address_zero], dividendName, { + from: token_owner, + value: new BN(web3.utils.toWei("10", "ether")) + }) + ); }); it("Non-owner pushes investor 1 - fails", async () => { - let investor1Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let investor1Balance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = new BN(await I_PolyToken.balanceOf(account_investor3)); await catchRevert( I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor2, account_investor1], { from: account_investor2, @@ -623,9 +622,9 @@ contract("EtherDividendCheckpoint", accounts => { }); it("issuer pushes investor 1 with bad dividend index - fails", async () => { - let investor1Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor1)); - let investor2Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor2)); - let investor3Balance = new BigNumber(await I_PolyToken.balanceOf(account_investor3)); + let investor1Balance = new BN(await I_PolyToken.balanceOf(account_investor1)); + let investor2Balance = new BN(await I_PolyToken.balanceOf(account_investor2)); + let investor3Balance = new BN(await I_PolyToken.balanceOf(account_investor3)); await catchRevert( I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(6, [account_investor2, account_investor1], { from: token_owner, @@ -640,48 +639,48 @@ contract("EtherDividendCheckpoint", accounts => { 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")); + assert.equal(dividendAmount1[0].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + assert.equal(dividendAmount1[1].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + assert.equal(dividendAmount2[0].toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + assert.equal(dividendAmount2[1].toString(), new BN(web3.utils.toWei("0.4", "ether")).toString()); + assert.equal(dividendAmount3[0].toString(), new BN(web3.utils.toWei("7", "ether")).toString()); + assert.equal(dividendAmount3[1].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + assert.equal(dividendAmount_temp[0].toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal(dividendAmount_temp[1].toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); it("Investor 2 claims dividend", async () => { - let investor1Balance = new BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2Balance = new BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3Balance = new BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalance = new BigNumber(await web3.eth.getBalance(account_temp)); + let investor1Balance = new BN(await web3.eth.getBalance(account_investor1)); + let investor2Balance = new BN(await web3.eth.getBalance(account_investor2)); + let investor3Balance = new BN(await web3.eth.getBalance(account_investor3)); + let tempBalance = new BN(await web3.eth.getBalance(account_temp)); await I_EtherDividendCheckpoint.pullDividendPayment(3, { from: account_investor2, gasPrice: 0 }); - 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)); - let tempBalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_temp)); + let investor1BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter1 = new BN(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).toString(), new BN(web3.utils.toWei("1.6", "ether")).toString()); 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 = 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)); - let tempBalanceAfter1 = new BigNumber(await web3.eth.getBalance(account_temp)); + let investor1BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter1 = new BN(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter1 = new BN(await web3.eth.getBalance(account_temp)); await I_EtherDividendCheckpoint.pushDividendPaymentToAddresses(3, [account_investor1, account_temp], { 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)); - let tempBalanceAfter2 = new BigNumber(await web3.eth.getBalance(account_temp)); + let investor1BalanceAfter2 = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter2 = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter2 = new BN(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter2 = new BN(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")); + assert.equal(tempBalanceAfter2.sub(tempBalanceAfter1).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); //Check fully claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(3))[5].toNumber(), web3.utils.toWei("3", "ether")); + assert.equal((await I_EtherDividendCheckpoint.dividends(3))[5].toString(), new BN(web3.utils.toWei("3", "ether")).toString()); }); it("should calculate dividend after the push dividend payment", async () => { @@ -701,10 +700,10 @@ 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 BN(await web3.eth.getBalance(token_owner)); await I_EtherDividendCheckpoint.reclaimDividend(3, { from: token_owner, gasPrice: 0 }); - let tokenOwnerAfter = new BigNumber(await web3.eth.getBalance(token_owner)); - assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toNumber(), web3.utils.toWei("7", "ether")); + let tokenOwnerAfter = new BN(await web3.eth.getBalance(token_owner)); + assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); it("Issuer is able to reclaim dividend after expiry", async () => { @@ -718,9 +717,9 @@ contract("EtherDividendCheckpoint", accounts => { 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), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(1000000))), true, { from: account_issuer, @@ -730,47 +729,47 @@ contract("EtherDividendCheckpoint", accounts => { // 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")); + await I_SecurityToken.mint(I_PolyToken.address, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_temp)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(I_PolyToken.address)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Create another new dividend", async () => { - let maturity = latestTime(); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime(); + let expiry = await latestTime() + duration.days(10); let tx = await I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, [], dividendName, { from: token_owner, - value: web3.utils.toWei("12", "ether") + value: new BN(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 = new BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceBefore = new BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceBefore = new BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceBefore = new BigNumber(await web3.eth.getBalance(account_temp)); - let tokenBalanceBefore = new BigNumber(await web3.eth.getBalance(I_PolyToken.address)); - - await I_EtherDividendCheckpoint.pushDividendPayment(4, 0, 10, { from: token_owner }); - - let investor1BalanceAfter = new BigNumber(await web3.eth.getBalance(account_investor1)); - let investor2BalanceAfter = new BigNumber(await web3.eth.getBalance(account_investor2)); - let investor3BalanceAfter = new BigNumber(await web3.eth.getBalance(account_investor3)); - let tempBalanceAfter = new BigNumber(await web3.eth.getBalance(account_temp)); - 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(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")); + let investor1BalanceBefore = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceBefore = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceBefore = new BN(await web3.eth.getBalance(account_investor3)); + let tempBalanceBefore = new BN(await web3.eth.getBalance(account_temp)); + let tokenBalanceBefore = new BN(await web3.eth.getBalance(I_PolyToken.address)); + + await I_EtherDividendCheckpoint.pushDividendPayment(4, new BN(0), 10, { from: token_owner }); + + let investor1BalanceAfter = new BN(await web3.eth.getBalance(account_investor1)); + let investor2BalanceAfter = new BN(await web3.eth.getBalance(account_investor2)); + let investor3BalanceAfter = new BN(await web3.eth.getBalance(account_investor3)); + let tempBalanceAfter = new BN(await web3.eth.getBalance(account_temp)); + let tokenBalanceAfter = new BN(await web3.eth.getBalance(I_PolyToken.address)); + + assert.equal(investor1BalanceAfter.sub(investor1BalanceBefore).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal(investor2BalanceAfter.sub(investor2BalanceBefore).toString(), new BN(web3.utils.toWei("1.6", "ether")).toString()); + assert.equal(investor3BalanceAfter.sub(investor3BalanceBefore).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); + assert.equal(tempBalanceAfter.sub(tempBalanceBefore).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal(tokenBalanceAfter.sub(tokenBalanceBefore).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); //Check partially claimed - assert.equal((await I_EtherDividendCheckpoint.dividends(4))[5].toNumber(), web3.utils.toWei("11", "ether")); + assert.equal((await I_EtherDividendCheckpoint.dividends(4))[5].toString(), new BN(web3.utils.toWei("11", "ether")).toString()); }); it("Should give the right dividend index", async () => { @@ -795,7 +794,7 @@ contract("EtherDividendCheckpoint", accounts => { it("should registr a delegate", async () => { [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); - let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", new BN(0), new BN(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, ""), @@ -803,65 +802,65 @@ contract("EtherDividendCheckpoint", accounts => { "GeneralPermissionManagerFactory module was not added" ); I_GeneralPermissionManager = await GeneralPermissionManager.at(tx.logs[2].args._module); - tx = await I_GeneralPermissionManager.addDelegate(account_manager, managerDetails, { from: token_owner}); + tx = await I_GeneralPermissionManager.addDelegate(account_manager, managerDetails, { from: token_owner }); assert.equal(tx.logs[0].args._delegate, account_manager); }); it("should not allow manager without permission to create dividend", async () => { - await I_PolyToken.transfer(account_manager, web3.utils.toWei("2", "ether"), { from: token_owner }); - await I_PolyToken.approve(I_EtherDividendCheckpoint.address, web3.utils.toWei("1.5", "ether"), { from: account_manager }); - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + await I_PolyToken.transfer(account_manager, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + await I_PolyToken.approve(I_EtherDividendCheckpoint.address, new BN(web3.utils.toWei("1.5", "ether")), { from: account_manager }); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); - await catchRevert(I_EtherDividendCheckpoint.createDividend( - maturity, - expiry, - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - )); + await catchRevert( + I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { + from: account_manager, + value: new BN(web3.utils.toWei("12", "ether")) + }) + ); }); it("should not allow manager without permission to create dividend with checkpoint", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); - await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpoint( - maturity, - expiry, - checkpointID.toNumber(), - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - )); + await catchRevert( + I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, checkpointID.toNumber(), dividendName, { + from: account_manager, + value: new BN(web3.utils.toWei("12", "ether")) + }) + ); }); it("should not allow manager without permission to create dividend with exclusion", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let exclusions = [1]; - await catchRevert(I_EtherDividendCheckpoint.createDividendWithExclusions( - maturity, - expiry, - exclusions, - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - )); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; + await catchRevert( + I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, exclusions, dividendName, { + from: account_manager, + value: new BN(web3.utils.toWei("12", "ether")) + }) + ); }); it("should not allow manager without permission to create dividend with checkpoint and exclusion", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let exclusions = [1]; + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); - await catchRevert(I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( - maturity, - expiry, - checkpointID.toNumber(), - exclusions, - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - )); + await catchRevert( + I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( + maturity, + expiry, + checkpointID.toNumber(), + exclusions, + dividendName, + { from: account_manager, value: new BN(web3.utils.toWei("12", "ether")) } + ) + ); }); it("should not allow manager without permission to create checkpoint", async () => { @@ -869,69 +868,53 @@ contract("EtherDividendCheckpoint", accounts => { }); it("should give permission to manager", async () => { - await I_GeneralPermissionManager.changePermission( - account_manager, - I_EtherDividendCheckpoint.address, - "CHECKPOINT", - true, - { from: token_owner } - ); - let tx = await I_GeneralPermissionManager.changePermission( - account_manager, - I_EtherDividendCheckpoint.address, - "MANAGE", - true, - { from: token_owner } - ); + await I_GeneralPermissionManager.changePermission(account_manager, I_EtherDividendCheckpoint.address, web3.utils.fromAscii("CHECKPOINT"), true, { + from: token_owner + }); + let tx = await I_GeneralPermissionManager.changePermission(account_manager, I_EtherDividendCheckpoint.address, web3.utils.fromAscii("MANAGE"), true, { + from: token_owner + }); assert.equal(tx.logs[0].args._delegate, account_manager); }); it("should allow manager with permission to create dividend", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); - let tx = await I_EtherDividendCheckpoint.createDividend( - maturity, - expiry, - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - ); + let tx = await I_EtherDividendCheckpoint.createDividend(maturity, expiry, dividendName, { + from: account_manager, + value: new BN(web3.utils.toWei("12", "ether")) + }); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 9); }); it("should allow manager with permission to create dividend with checkpoint", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); - let tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint( - maturity, - expiry, - checkpointID.toNumber(), - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - ); + let tx = await I_EtherDividendCheckpoint.createDividendWithCheckpoint(maturity, expiry, checkpointID.toNumber(), dividendName, { + from: account_manager, + value: new BN(web3.utils.toWei("12", "ether")) + }); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 10); }); 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 tx = await I_EtherDividendCheckpoint.createDividendWithExclusions( - maturity, - expiry, - exclusions, - dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } - ); + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; + let tx = await I_EtherDividendCheckpoint.createDividendWithExclusions(maturity, expiry, exclusions, dividendName, { + from: account_manager, + value: new BN(web3.utils.toWei("12", "ether")) + }); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 11); }); it("should allow manager with permission to create dividend with checkpoint and exclusion", async () => { - let maturity = latestTime() + duration.days(1); - let expiry = latestTime() + duration.days(10); - let exclusions = [1]; + let maturity = await latestTime() + duration.days(1); + let expiry = await latestTime() + duration.days(10); + let exclusions = [one_address]; let checkpointID = await I_SecurityToken.createCheckpoint.call({ from: token_owner }); await I_SecurityToken.createCheckpoint({ from: token_owner }); let tx = await I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions( @@ -940,7 +923,7 @@ contract("EtherDividendCheckpoint", accounts => { checkpointID.toNumber(), exclusions, dividendName, - { from: account_manager, value: web3.utils.toWei("12", "ether") } + { from: account_manager, value: new BN(web3.utils.toWei("12", "ether")) } ); assert.equal(tx.logs[0].args._checkpointId.toNumber(), 12); }); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index c1081ddbc..6792d6d17 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -1,21 +1,20 @@ -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 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 } from "./helpers/createInstances"; -const SecurityToken = artifacts.require('./SecurityToken.sol'); -const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); -const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +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('GeneralPermissionManager', accounts => { +const Web3 = require("web3"); +const BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port +contract("GeneralPermissionManager", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -28,10 +27,7 @@ contract('GeneralPermissionManager', accounts => { let account_delegate; let account_delegate2; let account_delegate3; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); + const delegateDetails = web3.utils.fromAscii("I am delegate"); let message = "Transaction Should Fail!"; @@ -62,7 +58,7 @@ contract('GeneralPermissionManager', accounts => { const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; - const delegateDetails = "Hello I am legit delegate"; + const managerDetails = web3.utils.fromAscii("Hello"); // Module key const delegateManagerKey = 1; @@ -70,10 +66,14 @@ contract('GeneralPermissionManager', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); + + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; - before(async() => { - // Accounts setup + before(async () => { + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -107,7 +107,7 @@ contract('GeneralPermissionManager', accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 6: Deploy the GeneralDelegateManagerFactory - [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, new BN(web3.utils.toWei("500"))); // Printing all the contract addresses console.log(` @@ -136,15 +136,15 @@ contract('GeneralPermissionManager', 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -153,25 +153,27 @@ contract('GeneralPermissionManager', accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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 I_PolyToken.getTokens(new BN(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 }) + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(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 }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_GeneralPermissionManagerFactory.address, "0x", - web3.utils.toWei("500", "ether"), - 0, + new BN(web3.utils.toWei("500", "ether")), + new BN(0), { from: token_owner } ); assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); @@ -180,21 +182,20 @@ contract('GeneralPermissionManager', accounts => { "GeneralPermissionManager", "GeneralPermissionManagerFactory module was not added" ); - P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); + P_GeneralPermissionManager = await 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 }); + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", new BN(0), new BN(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); + I_GeneralPermissionManager = await GeneralPermissionManager.at(tx.logs[2].args._module); }); - }); describe("General Permission Manager test cases", async () => { @@ -203,51 +204,43 @@ contract('GeneralPermissionManager', accounts => { assert.equal(web3.utils.toAscii(tx).replace(/\u0000/g, ""), 0); }); - it("Should fail in adding the delegate -- msg.sender doesn't have permission", async() => { + it("Should fail in adding the delegate -- msg.sender doesn't have permission", async () => { let errorThrown = false; - await catchRevert( - I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}) - ); + await catchRevert(I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1 })); }); - it("Should fail in adding the delegate -- no delegate details provided", async() => { - await catchRevert( - I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: token_owner }) - ); + it("Should fail in adding the delegate -- no delegate details provided", async () => { + await catchRevert(I_GeneralPermissionManager.addDelegate(account_delegate, "0x0", { from: token_owner })); }); - it("Should fail in adding the delegate -- no delegate address provided", async() => { - await catchRevert( - I_GeneralPermissionManager.addDelegate('', delegateDetails, { from: token_owner }) - ); + it("Should fail in adding the delegate -- no delegate address provided", async () => { + await catchRevert(I_GeneralPermissionManager.addDelegate(address_zero, delegateDetails, { from: token_owner })); }); - it("Should fail to remove the delegate -- failed because delegate does not exisit", async() => { - await catchRevert( - I_GeneralPermissionManager.deleteDelegate(account_delegate, { from: token_owner}) - ); + it("Should fail to remove the delegate -- failed because delegate does not exisit", async () => { + await catchRevert(I_GeneralPermissionManager.deleteDelegate(account_delegate, { from: token_owner })); }); - it("Should successfully add the delegate", async() => { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); + 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 successfully add the delegate -- failed because trying to add the already present delegate", async() => { + it("Should successfully add the delegate -- failed because trying to add the already present delegate", async () => { + await catchRevert(I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner })); + }); + + it("Should fail to provide the permission -- because msg.sender doesn't have permission", async () => { await catchRevert( - I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}) + I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"), true, { + from: account_investor1 + }) ); - }) - - it("Should fail to provide the permission -- because msg.sender doesn't have permission", async() => { - await catchRevert( - I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}) - ); }); it("Should check the permission", async () => { assert.isFalse( - await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST") + await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST")) ); }); @@ -255,7 +248,7 @@ contract('GeneralPermissionManager', accounts => { let tx = await I_GeneralPermissionManager.changePermission( account_delegate, I_GeneralTransferManager.address, - "WHITELIST", + web3.utils.fromAscii("WHITELIST"), true, { from: token_owner } ); @@ -264,47 +257,42 @@ contract('GeneralPermissionManager', accounts => { it("Should check the permission", async () => { assert.isTrue( - await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST") + await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST")) ); }); it("Security token should deny all permission if all permission managers are disabled", async () => { await I_SecurityToken.archiveModule(I_GeneralPermissionManager.address, { from: token_owner }); - assert.isFalse( - await I_SecurityToken.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST") - ); + assert.isFalse(await I_SecurityToken.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))); await I_SecurityToken.unarchiveModule(I_GeneralPermissionManager.address, { from: token_owner }); - assert.isTrue( - await I_SecurityToken.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST") - ); + assert.isTrue(await I_SecurityToken.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))); }); - it("Should fail to remove the delegate -- failed because unauthorized msg.sender", async() => { - await catchRevert( - I_GeneralPermissionManager.deleteDelegate(account_delegate, { from: account_delegate}) - ); + it("Should fail to remove the delegate -- failed because unauthorized msg.sender", async () => { + await catchRevert(I_GeneralPermissionManager.deleteDelegate(account_delegate, { from: account_delegate })); }); - it("Should remove the delegate", async() => { - await I_GeneralPermissionManager.deleteDelegate(account_delegate, { from: token_owner}) + it("Should remove the delegate", async () => { + await I_GeneralPermissionManager.deleteDelegate(account_delegate, { from: token_owner }); }); it("Should check the permission", async () => { assert.isFalse( - await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "WHITELIST") + await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST")) ); }); - it("Should successfully add the delegate", async() => { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); + 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 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 check the delegate details", async () => { + assert.equal( + web3.utils.toAscii(await I_GeneralPermissionManager.delegateDetails.call(account_delegate)).replace(/\u0000/g, ""), + web3.utils.toAscii(delegateDetails), + "Wrong delegate address get checked" + ); }); it("Should get the permission of the general permission manager contract", async () => { @@ -312,84 +300,116 @@ contract('GeneralPermissionManager', accounts => { 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}); + it("Should return all delegates", async () => { + await I_GeneralPermissionManager.addDelegate(account_delegate2, delegateDetails, { from: token_owner }); let tx = await I_GeneralPermissionManager.getAllDelegates.call(); assert.equal(tx.length, 2); - assert.equal(tx[0], account_delegate); + assert.equal(tx[0], account_delegate); assert.equal(tx[1], account_delegate2); }); - it("Should check is delegate for 0x address - failed 0x address is not allowed", async() => { - await catchRevert( - I_GeneralPermissionManager.checkDelegate.call("0x0000000000000000000000000000000000000000000000000") - ); + it("Should check is delegate for 0x address - failed 0x address is not allowed", async () => { + await catchRevert(I_GeneralPermissionManager.checkDelegate.call(address_zero)); }); - it("Should return false when check is delegate - because user is not a delegate", async() => { + 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() => { + 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 successfully provide the permissions in batch -- failed because of array length is 0", async() => { - await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner}); + it("Should successfully provide the permissions in batch -- failed because of array length is 0", async () => { + await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner }); await catchRevert( - I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}) + I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [], [web3.utils.fromAscii("WHITELIST"), web3.utils.fromAscii("CHANGE_PERMISSION")], [true, true], { + from: token_owner + }) ); }); - it("Should successfully provide the permissions in batch -- failed because of perm array length is 0", async() => { + it("Should successfully provide the permissions in batch -- failed because of perm array length is 0", async () => { await catchRevert( - I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], [], [true, true], {from: token_owner}) + I_GeneralPermissionManager.changePermissionMulti( + account_delegate3, + [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], + [], + [true, true], + { from: token_owner } + ) ); }); - it("Should successfully provide the permissions in batch -- failed because mismatch in arrays length", async() => { + it("Should successfully provide the permissions in batch -- failed because mismatch in arrays length", async () => { await catchRevert( - I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}) + I_GeneralPermissionManager.changePermissionMulti( + account_delegate3, + [I_GeneralTransferManager.address], + [web3.utils.fromAscii("WHITELIST"), web3.utils.fromAscii("CHANGE_PERMISSION")], + [true, true], + { from: token_owner } + ) ); }); - it("Should successfully provide the permissions in batch -- failed because mismatch in arrays length", async() => { + it("Should successfully provide the permissions in batch -- failed because mismatch in arrays length", async () => { await catchRevert( - I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true], {from: token_owner}) + I_GeneralPermissionManager.changePermissionMulti( + account_delegate3, + [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], + [web3.utils.fromAscii("WHITELIST"), web3.utils.fromAscii("CHANGE_PERMISSION")], + [true], + { from: token_owner } + ) ); }); - it("Should successfully provide the permissions in batch", async() => { - let tx = await I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}); + it("Should successfully provide the permissions in batch", async () => { + let tx = await I_GeneralPermissionManager.changePermissionMulti( + account_delegate3, + [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], + [web3.utils.fromAscii("WHITELIST"), web3.utils.fromAscii("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, web3.utils.fromAscii("WHITELIST")) + ); + assert.isTrue( + await I_GeneralPermissionManager.checkPermission.call( + account_delegate3, + I_GeneralPermissionManager.address, + web3.utils.fromAscii("CHANGE_PERMISSION") + ) + ); }); - it("Should provide all delegates with specified permission", async() => { - 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"); + it("Should provide all delegates with specified permission", async () => { + await I_GeneralPermissionManager.changePermission(account_delegate2, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"), true, { + from: token_owner + }); + let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST")); assert.equal(tx.length, 3); assert.equal(tx[0], account_delegate); assert.equal(tx[1], account_delegate2); }); - it("Should get all delegates for the permission manager", async() => { - let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralPermissionManager.address, "CHANGE_PERMISSION"); + it("Should get all delegates for the permission manager", async () => { + let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralPermissionManager.address, web3.utils.fromAscii("CHANGE_PERMISSION")); assert.equal(tx.length, 1); assert.equal(tx[0], account_delegate3); - }) + }); - it("Should return all modules and all permission", async() => { - let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2,1]); + it("Should return all modules and all permission", async () => { + let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2, 1]); 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 () => { @@ -420,9 +440,9 @@ contract('GeneralPermissionManager', accounts => { assert.equal(tags.length, 0); }); - it("Should ge the version of the factory", async() => { + it("Should ge the version of the factory", async () => { 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 457898b58..4876765fc 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -7,17 +7,16 @@ import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed, deployGTMAndVerifyed } from "./helpers/createInstances"; - const DummySTO = artifacts.require("./DummySTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("GeneralTransferManager", accounts => { +contract("GeneralTransferManager", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -32,9 +31,9 @@ contract("GeneralTransferManager", accounts => { let account_affiliates2; // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); + let fromTime; + let toTime; + let expiryTime; let message = "Transaction Should Fail!"; @@ -73,17 +72,27 @@ contract("GeneralTransferManager", accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(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"); + let startTime; + let endTime; + const cap = new BN(web3.utils.toWei("10", "ether")); const someString = "A string which is not used"; const STOParameters = ["uint256", "uint256", "uint256", "string"]; + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); + fromTime = await latestTime(); + toTime = await latestTime(); + expiryTime = toTime + duration.days(15); + startTime = await latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time + endTime = startTime + duration.days(80); // Add 80 days more + account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -118,9 +127,9 @@ contract("GeneralTransferManager", accounts => { ] = instances; [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); - [P_GeneralTransferManagerFactory] = await deployGTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [P_GeneralTransferManagerFactory] = await deployGTMAndVerifyed(account_polymath, I_MRProxied, new BN(web3.utils.toWei("500"))); [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, 0); - [P_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [P_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, new BN(web3.utils.toWei("500"))); // Printing all the contract addresses console.log(` @@ -151,15 +160,15 @@ contract("GeneralTransferManager", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -168,28 +177,30 @@ contract("GeneralTransferManager", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); - it("Should attach the paid GTM -- failed because of no tokens", async() => { + it("Should attach the paid GTM -- failed because of no tokens", async () => { await catchRevert( - I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}) + I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "0x0", new BN(web3.utils.toWei("500")), new BN(0), { from: account_issuer }) ); }); - it("Should attach the paid GTM", async() => { + 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 I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "0x0", new BN(web3.utils.toWei("500")), new BN(0), { + from: account_issuer + }); await revertToSnapshot(snap_id); }); 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)], + [currentTime + currentTime.add(new BN(duration.days(30))), currentTime.add(new BN(duration.days(30)))], + [currentTime + currentTime.add(new BN(duration.days(90))), currentTime.add(new BN(duration.days(90)))], + [currentTime + currentTime.add(new BN(duration.days(965))), currentTime.add(new BN(duration.days(365)))], [false, false], { from: account_issuer, @@ -206,110 +217,102 @@ contract("GeneralTransferManager", accounts => { 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()); + 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 - } - ); + 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)); + assert.deepEqual( + await I_GeneralTransferManager.getInvestors.call(), + [account_affiliates1, account_affiliates2].concat(mockInvestors) + ); }); 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)], { + await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { 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); + assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).div(new BN(10).pow(new BN(18))).toNumber(), 100); + assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).div(new BN(10).pow(new BN(18))).toNumber(), 100); }); - it("Should successfully attach the STO factory with the security token -- failed because of no tokens", async () => { let bytesSTO = encodeModuleCall(STOParameters, [ - latestTime() + duration.seconds(1000), - latestTime() + duration.days(40), + await latestTime() + duration.seconds(1000), + await latestTime() + duration.days(40), cap, someString ]); await catchRevert( - I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: token_owner }) + I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { from: token_owner }) ); }); it("Should successfully attach the STO factory with the security token", async () => { let snap_id = await takeSnapshot(); let bytesSTO = encodeModuleCall(STOParameters, [ - latestTime() + duration.seconds(1000), - latestTime() + duration.days(40), + await latestTime() + duration.seconds(1000), + await latestTime() + duration.days(40), cap, someString ]); - await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: token_owner }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + from: token_owner + }); assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), "DummySTO", "DummySTOFactory module was not added" ); - I_DummySTO = DummySTO.at(tx.logs[3].args._module); + I_DummySTO = await DummySTO.at(tx.logs[3].args._module); await revertToSnapshot(snap_id); }); it("Should successfully attach the STO factory with the security token - invalid data", async () => { - let bytesSTO = encodeModuleCall(['uint256', 'string'], [ - latestTime() + duration.seconds(1000), - someString - ]); - await catchRevert( - I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }) - ); + let bytesSTO = encodeModuleCall(["uint256", "string"], [await latestTime() + duration.seconds(1000), someString]); + await catchRevert(I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); }); it("Should successfully attach the STO factory with the security token", async () => { let bytesSTO = encodeModuleCall(STOParameters, [ - latestTime() + duration.seconds(1000), - latestTime() + duration.days(40), + await latestTime() + duration.seconds(1000), + await latestTime() + duration.days(40), cap, someString ]); - const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, new BN(0), new BN(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); + I_DummySTO = await 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 }); + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, new BN(0), new BN(0), new BN(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); + I_GeneralPermissionManager = await 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 () => { - await catchRevert(I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner })); + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); }); it("Should Buy the tokens", async () => { @@ -317,9 +320,9 @@ contract("GeneralTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -337,37 +340,35 @@ contract("GeneralTransferManager", accounts => { await increaseTime(5000); // Mint some tokens - await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should fail in buying the token from the STO", async () => { - await catchRevert(I_DummySTO.generateTokens(account_affiliates1, web3.utils.toWei("1", "ether"), { from: token_owner })); + await catchRevert(I_DummySTO.generateTokens(account_affiliates1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); }); - 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 amount is 0", async () => { + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(0), { from: token_owner })); }); - it("Should fail in buying the tokens from the STO -- because STO is paused", async() => { - await I_DummySTO.pause({from: account_issuer }); - await catchRevert(I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner })); + it("Should fail in buying the tokens from the STO -- because STO is paused", async () => { + await I_DummySTO.pause({ from: account_issuer }); + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); // Reverting the changes releated to pause - await I_DummySTO.unpause({from: account_issuer }); + await I_DummySTO.unpause({ from: account_issuer }); }); - it("Should buy more tokens from the STO to investor1", async() => { - 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("2", "ether")); + it("Should buy more tokens from the STO to investor1", async () => { + await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Should fail in investing the money in STO -- expiry limit reached", async () => { await increaseTime(duration.days(10)); - await catchRevert(I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner })); + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); }); }); @@ -377,17 +378,10 @@ contract("GeneralTransferManager", accounts => { 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 - } - ); + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, new BN(0), new BN(0), currentTime.add(new BN(duration.days(20))), true, { + from: account_issuer, + gas: 6000000 + }); assert.equal( tx.logs[0].args._investor.toLowerCase(), @@ -397,9 +391,9 @@ contract("GeneralTransferManager", accounts => { tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(20), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(20))), true, { from: account_issuer, @@ -417,54 +411,44 @@ contract("GeneralTransferManager", accounts => { 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")); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); 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})); + let tx = await I_GeneralTransferManager.changeDefaults(currentTime.add(new BN(duration.days(12))), new BN(0), { from: token_owner }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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}); + await I_SecurityToken.transfer(account_investor2, new BN(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}); + let tx = await I_GeneralTransferManager.changeDefaults(0, currentTime.add(new BN(duration.days(16))), { from: token_owner }); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + await increaseTime(duration.days(2)); + await I_SecurityToken.transfer(account_investor1, new BN(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}); + await I_GeneralTransferManager.modifyWhitelist(account_investor2, new BN(0), new BN(0), new BN(0), false, { + from: account_issuer, + gas: 6000000 + }); + await I_GeneralTransferManager.changeDefaults(0, new BN(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 })); + await catchRevert(I_DummySTO.generateTokens(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); }); 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); + let validFrom = await latestTime(); + let validTo = await latestTime() + duration.days(5); let nonce = 5; const sig = signData( account_investor2, @@ -507,8 +491,8 @@ contract("GeneralTransferManager", accounts => { 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; + let validFrom = await latestTime() - 100; + let validTo = await latestTime() - 1; let nonce = 5; const sig = signData( I_GeneralTransferManager.address, @@ -551,8 +535,8 @@ contract("GeneralTransferManager", accounts => { 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; + let validFrom = await latestTime(); + let validTo = await latestTime() + 60 * 60; let nonce = 5; const sig = signData( account_investor2, @@ -595,14 +579,14 @@ contract("GeneralTransferManager", accounts => { 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); + let validFrom = await latestTime(); + let validTo = await latestTime() + duration.days(5); let nonce = 5; const sig = signData( I_GeneralTransferManager.address, account_investor2, - latestTime(), - latestTime() + duration.days(80), + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), true, validFrom, @@ -617,8 +601,8 @@ contract("GeneralTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelistSigned( account_investor2, - latestTime(), - latestTime() + duration.days(80), + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), true, validFrom, @@ -643,22 +627,22 @@ contract("GeneralTransferManager", accounts => { await increaseTime(10000); // Mint some tokens - await I_DummySTO.generateTokens(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_DummySTO.generateTokens(account_investor2, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); - it("Should fail if the txn is generated with same nonce", async() => { + 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 validFrom = await latestTime(); + let validTo = await latestTime() + duration.days(5); let nonce = 5; const sig = signData( I_GeneralTransferManager.address, account_investor2, - latestTime(), - latestTime() + duration.days(80), + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), true, validFrom, @@ -671,25 +655,26 @@ contract("GeneralTransferManager", accounts => { 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 - } - ) + await catchRevert( + I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + 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 })); @@ -701,16 +686,16 @@ contract("GeneralTransferManager", accounts => { 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}); + it("Should provide the permission and change the signing address", async () => { + let log = await I_GeneralPermissionManager.addDelegate(account_delegate, web3.utils.fromAscii("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, { + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { from: token_owner }); assert.isTrue( - await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, "FLAGS") + await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS")) ); let tx = await I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_delegate }); @@ -718,29 +703,29 @@ contract("GeneralTransferManager", accounts => { }); it("Should fail to pull fees as no budget set", async () => { - await catchRevert(I_GeneralTransferManager.takeFee(web3.utils.toWei("1", "ether"), { from: account_polymath })); + await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_polymath })); }); it("Should set a budget for the GeneralTransferManager", async () => { - await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), true, { from: token_owner }); + await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, new BN(10).pow(new BN(19)), 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); - await I_PolyToken.transfer(I_SecurityToken.address, 10 * Math.pow(10, 18), { from: token_owner }); + await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + await I_PolyToken.getTokens(new BN(10).pow(new BN(19)), token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(10).pow(new BN(19)), { from: token_owner }); }); it("Factory owner should pull fees - fails as not permissioned by issuer", async () => { - await catchRevert(I_GeneralTransferManager.takeFee(web3.utils.toWei("1", "ether"), { from: account_delegate })); + await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate })); }); it("Factory owner should pull fees", async () => { - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "FEE_ADMIN", true, { + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("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 }); + await I_GeneralTransferManager.takeFee(new BN(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"); + assert.equal(balanceBefore.add(new BN(web3.utils.toWei("1", "ether"))).toString(), balanceAfter.toString(), "Fee is transferred"); }); it("Should change the white list transfer variable", async () => { @@ -751,7 +736,7 @@ contract("GeneralTransferManager", accounts => { 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 }); - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("2", "ether"), { from: account_investor2 })); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); }); it("Should change the Issuance address", async () => { @@ -773,8 +758,8 @@ contract("GeneralTransferManager", accounts => { 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 fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); await catchRevert( @@ -793,8 +778,8 @@ contract("GeneralTransferManager", accounts => { }); it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); await catchRevert( @@ -813,8 +798,8 @@ contract("GeneralTransferManager", accounts => { }); it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); await catchRevert( @@ -833,8 +818,8 @@ contract("GeneralTransferManager", accounts => { }); it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); await catchRevert( @@ -853,8 +838,8 @@ contract("GeneralTransferManager", accounts => { }); it("Should successfully add the investors in whitelist", async () => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(20); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); let tx = await I_GeneralTransferManager.modifyWhitelistMulti( @@ -920,7 +905,7 @@ contract("GeneralTransferManager", accounts => { assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Dummy"); }); - it("Should get the version of factory", async() => { + it("Should get the version of factory", async () => { let version = await I_DummySTOFactory.version.call(); assert.equal(version, "1.0.0"); }); @@ -928,11 +913,11 @@ contract("GeneralTransferManager", accounts => { 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")); + assert.equal((await I_DummySTO.getRaised.call(0)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); it("Should get the raised amount of poly", async () => { - assert.equal((await I_DummySTO.getRaised.call(1)).toNumber(), web3.utils.toWei("0", "ether")); + assert.equal((await I_DummySTO.getRaised.call(1)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); }); it("Should get the investors", async () => { @@ -944,11 +929,15 @@ contract("GeneralTransferManager", accounts => { assert.equal(web3.utils.toAscii(tx[0]).replace(/\u0000/g, ""), "ADMIN"); }); - it("Should get the amount of tokens sold", async() => { + it("Should get the amount of tokens sold", async () => { assert.equal(await I_DummySTO.getTokensSold.call(), 0); - }) + }); }); }); -function range1(i) {return i?range1(i-1).concat(i):[]} -function rangeB(i) {return i?rangeB(i-1).concat(0):[]} +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/contracts/PolyToken.sol b/test/helpers/contracts/PolyToken.sol index 6f39af814..b9863b0c2 100644 --- a/test/helpers/contracts/PolyToken.sol +++ b/test/helpers/contracts/PolyToken.sol @@ -1,11 +1,9 @@ -pragma solidity ^0.4.24; +pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; - contract PolyToken is ERC20Mintable { - - constructor () public { + constructor() public { } diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 9a8ada346..4c9f6090c 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -41,6 +41,7 @@ const STRGetter = artifacts.require("./STRGetter.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); const Web3 = require("web3"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port // Contract Instance Declaration @@ -87,7 +88,7 @@ let I_MRProxied; let I_STRGetter; // Initial fee for ticker registry and security token registry -const initRegFee = web3.utils.toWei("250"); +const initRegFee = new BN(web3.utils.toWei("250")); const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; const MRProxyParameters = ["address", "address"]; @@ -114,18 +115,30 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { await setInPolymathRegistry(account_polymath); // STEP 9: Register the Modules with the ModuleRegistry contract await registerGTM(account_polymath); - let tempArray = new Array(a, b, c, d, e, f); - return mergeReturn(tempArray); + let tempArray = new Array( + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied, + I_STRGetter + ); + return Promise.all(tempArray); } - async function deployPolyRegistryAndPolyToken(account_polymath, token_owner) { // 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); + await I_PolyToken.getTokens(new BN(10000).mul(new BN(10).pow(new BN(18))), token_owner); await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { from: account_polymath }); @@ -152,7 +165,11 @@ async function deployModuleRegistry(account_polymath) { } async function deployGTMLogic(account_polymath) { - I_GeneralTransferManagerLogic = await GeneralTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); + I_GeneralTransferManagerLogic = await GeneralTransferManager.new( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + { from: account_polymath } + ); assert.notEqual( I_GeneralTransferManagerLogic.address.valueOf(), @@ -164,7 +181,9 @@ async function deployGTMLogic(account_polymath) { } async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, 0, 0, I_GeneralTransferManagerLogic.address, { from: account_polymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(new BN(0), new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { + from: account_polymath + }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -205,8 +224,8 @@ async function deploySTR(account_polymath) { I_STRGetter.address ]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }); - I_STRProxied = SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + I_STRGetter = await STRGetter.at(I_SecurityTokenRegistryProxy.address); return new Array(I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, I_STRGetter); } @@ -231,7 +250,9 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, 0, 0, I_GeneralTransferManagerLogic.address, { from: accountPolymath }); + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { + from: accountPolymath + }); assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), @@ -241,12 +262,12 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, set // (B) : Register the GeneralDelegateManagerFactory await registerAndVerifyByMR(I_GeneralTransferManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_GeneralTransferManagerFactory); + return Promise.all(new Array(I_GeneralTransferManagerFactory)); } export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_CountTransferManagerLogic = await CountTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, 0, 0, I_CountTransferManagerLogic.address, { from: accountPolymath }); + I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_CountTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_CountTransferManagerFactory.address.valueOf(), @@ -255,12 +276,12 @@ export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, ); await registerAndVerifyByMR(I_CountTransferManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_CountTransferManagerFactory); + return Promise.all(new Array(I_CountTransferManagerFactory)); } export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_ManualApprovalTransferManagerLogic = await ManualApprovalTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, 0, 0, ManualApprovalTransferManager.address, { from: accountPolymath }); + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, new BN(0), new BN(0), ManualApprovalTransferManager.address, { from: accountPolymath }); assert.notEqual( I_ManualApprovalTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -268,12 +289,12 @@ export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxy ); await registerAndVerifyByMR(I_ManualApprovalTransferManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_ManualApprovalTransferManagerFactory); + return Promise.all(new Array(I_ManualApprovalTransferManagerFactory)); } export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { I_PercentageTransferManagerLogic = await PercentageTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, 0, 0, I_PercentageTransferManagerLogic.address, { from: accountPolymath }); + I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_PercentageTransferManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_PercentageTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -281,11 +302,13 @@ export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInst ); await registerAndVerifyByMR(I_PercentageTransferManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_PercentageTransferManagerFactory); + return Promise.all(new Array(I_PercentageTransferManagerFactory)); } export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(setupCost, new BN(0), new BN(0), { + from: accountPolymath + }); assert.notEqual( I_VolumeRestrictionTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -293,11 +316,11 @@ export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyI ); await registerAndVerifyByMR(I_VolumeRestrictionTransferManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_VolumeRestrictionTransferManagerFactory); + return Promise.all(new Array(I_VolumeRestrictionTransferManagerFactory)); } export async function deployScheduleCheckpointAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); assert.notEqual( I_ScheduledCheckpointFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -305,14 +328,14 @@ export async function deployScheduleCheckpointAndVerified(accountPolymath, MRPro ); await registerAndVerifyByMR(I_ScheduledCheckpointFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_ScheduledCheckpointFactory); + return Promise.all(new Array(I_ScheduledCheckpointFactory)); } /// Deploy the Permission Manager export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, 0, 0, I_GeneralPermissionManagerLogic.address, { from: accountPolymath }); + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -322,15 +345,14 @@ export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, set // (B) : Register the GeneralDelegateManagerFactory await registerAndVerifyByMR(I_GeneralPermissionManagerFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_GeneralPermissionManagerFactory); + return Promise.all(new Array(I_GeneralPermissionManagerFactory)); } - /// Deploy the STO Modules export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_DummySTOLogic = await DummySTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_DummySTOFactory = await DummySTOFactory.new(setupCost, 0, 0, I_DummySTOLogic.address,{ from: accountPolymath }); + I_DummySTOFactory = await DummySTOFactory.new(setupCost, new BN(0), new BN(0), I_DummySTOLogic.address,{ from: accountPolymath }); assert.notEqual( I_DummySTOFactory.address.valueOf(), @@ -338,12 +360,12 @@ export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance "DummySTOFactory contract was not deployed" ); await registerAndVerifyByMR(I_DummySTOFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_DummySTOFactory); + return Promise.all(new Array(I_DummySTOFactory)); } export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_CappedSTOLogic = await CappedSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, 0, 0, I_CappedSTOLogic.address, { from: accountPolymath }); + I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, new BN(0), new BN(0), I_CappedSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_CappedSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -351,13 +373,12 @@ export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstanc ); await registerAndVerifyByMR(I_CappedSTOFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_CappedSTOFactory); - + return Promise.all(new Array(I_CappedSTOFactory)); } export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { I_PreSaleSTOLogic = await PreSaleSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, 0, 0, I_PreSaleSTOLogic.address, { from: accountPolymath }); + I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, new BN(0), new BN(0), I_PreSaleSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_PreSaleSTOFactory.address.valueOf(), @@ -366,13 +387,17 @@ export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstan ); await registerAndVerifyByMR(I_PreSaleSTOFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_PreSaleSTOFactory); + return Promise.all(new Array(I_PreSaleSTOFactory)); } export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_USDTieredSTOLogic = await USDTieredSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_USDTieredSTOLogic = await USDTieredSTO.new( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + { from: accountPolymath } + ); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, 0, 0, I_USDTieredSTOLogic.address, { from: accountPolymath }); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, new BN(0), new BN(0), I_USDTieredSTOLogic.address, { from: accountPolymath }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), @@ -381,15 +406,20 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst ); await registerAndVerifyByMR(I_USDTieredSTOFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_USDTieredSTOFactory); + return Promise.all(new Array(I_USDTieredSTOFactory)); } - /// Deploy the Dividend Modules export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, 0, 0, I_ERC20DividendCheckpointLogic.address, { from: accountPolymath }); + I_ERC20DividendCheckpointLogic = await ERC20DividendCheckpoint.new( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + { from: accountPolymath } + ); + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, new BN(0), new BN(0), I_ERC20DividendCheckpointLogic.address, { + from: accountPolymath + }); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -397,12 +427,18 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns "ERC20DividendCheckpointFactory contract was not deployed" ); await registerAndVerifyByMR(I_ERC20DividendCheckpointFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_ERC20DividendCheckpointFactory); + return Promise.all(new Array(I_ERC20DividendCheckpointFactory)); } export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, 0, 0, I_EtherDividendCheckpointLogic.address, { from: accountPolymath }); + I_EtherDividendCheckpointLogic = await EtherDividendCheckpoint.new( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + { from: accountPolymath } + ); + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, new BN(0), new BN(0), I_EtherDividendCheckpointLogic.address, { + from: accountPolymath + }); assert.notEqual( I_EtherDividendCheckpointFactory.address.valueOf(), @@ -411,14 +447,13 @@ export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyIns ); await registerAndVerifyByMR(I_EtherDividendCheckpointFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_EtherDividendCheckpointFactory); + return Promise.all(new Array(I_EtherDividendCheckpointFactory)); } - /// Deploy the Burn Module export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); assert.notEqual( I_TrackedRedemptionFactory.address.valueOf(), @@ -427,12 +462,11 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan ); await registerAndVerifyByMR(I_TrackedRedemptionFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_TrackedRedemptionFactory); + return Promise.all(new Array(I_TrackedRedemptionFactory)); } - export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_MockBurnFactory = await MockBurnFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_MockBurnFactory = await MockBurnFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); assert.notEqual( I_MockBurnFactory.address.valueOf(), @@ -441,11 +475,11 @@ export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyIn ); await registerAndVerifyByMR(I_MockBurnFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_MockBurnFactory); + return Promise.all(new Array(I_MockBurnFactory)); } export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); assert.notEqual( I_MockWrongTypeBurnFactory.address.valueOf(), @@ -454,18 +488,5 @@ export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, ); await registerAndVerifyByMR(I_MockWrongTypeBurnFactory.address, accountPolymath, MRProxyInstance); - return new Array(I_MockWrongTypeBurnFactory); -} - - - -/// Helper function -function mergeReturn(returnData) { - let returnArray = new Array(); - for (let i = 0; i < returnData.length; i++) { - for (let j = 0; j < returnData[i].length; j++) { - returnArray.push(returnData[i][j]); - } - } - return returnArray; + return Promise.all(new Array(I_MockWrongTypeBurnFactory)); } diff --git a/test/helpers/latestTime.js b/test/helpers/latestTime.js index 38c744969..58671e254 100644 --- a/test/helpers/latestTime.js +++ b/test/helpers/latestTime.js @@ -1,4 +1,9 @@ // Returns the time of the last mined block in seconds -export default function latestTime() { - return web3.eth.getBlock("latest").timestamp; +export default async function latestTime() { + let block = await latestBlock(); + return block.timestamp; +} + +async function latestBlock() { + return web3.eth.getBlock("latest"); } diff --git a/test/helpers/signData.js b/test/helpers/signData.js index ea7476cc3..f75572450 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -1,6 +1,8 @@ const ethers = require("ethers"); const utils = ethers.utils; const ethUtil = require("ethereumjs-util"); +const Web3 = require("web3"); +let BN = Web3.utils.BN; //this, _investor, _fromTime, _toTime, _validTo function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { @@ -12,7 +14,7 @@ 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 = web3.utils.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } diff --git a/test/helpers/time.js b/test/helpers/time.js index 3e3362d81..1bbe676ca 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -2,38 +2,71 @@ // aren’t included within the original RPC specification. // See https://github.com/ethereumjs/testrpc#implemented-methods -function increaseTime(duration) { - const id = Date.now(); +// async function increaseTime(duration) { +// //let currentTime = (await web3.eth.getBlock('latest')).timestamp +// await sendIncreaseTime(duration); +// return advanceBlock(); +// } - return new Promise((resolve, reject) => { - web3.currentProvider.sendAsync( - { - jsonrpc: "2.0", - method: "evm_increaseTime", - params: [duration], - id: id - }, - err1 => { - if (err1) return reject(err1); +// async function sendIncreaseTime(duration) { +// return new Promise(() => +// web3.currentProvider.send({ +// jsonrpc: '2.0', +// method: 'evm_increaseTime', +// params: [duration], +// }) +// ); +// } - web3.currentProvider.sendAsync( - { - jsonrpc: "2.0", - method: "evm_mine", - id: id + 1 - }, - (err2, res) => { - return err2 ? reject(err2) : resolve(res); - } - ); - } - ); - }); +// async function advanceBlock() { +// return new Promise(() => +// web3.currentProvider.send({ +// jsonrpc: '2.0', +// method: 'evm_mine', +// }) +// ); +// } + +const pify = require('pify'); + +function advanceBlock() { + return pify(web3.currentProvider.send)({ + jsonrpc: '2.0', + method: 'evm_mine', + }); +} + +// Increases ganache time by the passed duration in seconds +async function increaseTime(duration) { + await pify(web3.currentProvider.send)({ + jsonrpc: '2.0', + method: 'evm_increaseTime', + params: [duration], + }); + await advanceBlock(); +} + +async 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); + } + ); + }); } export default function takeSnapshot() { return new Promise((resolve, reject) => { - web3.currentProvider.sendAsync( + web3.currentProvider.send( { jsonrpc: "2.0", method: "evm_snapshot", @@ -51,9 +84,9 @@ export default function takeSnapshot() { }); } -function revertToSnapshot(snapShotId) { +async function revertToSnapshot(snapShotId) { return new Promise((resolve, reject) => { - web3.currentProvider.sendAsync( + web3.currentProvider.send( { jsonrpc: "2.0", method: "evm_revert", diff --git a/test/helpers/utils.js b/test/helpers/utils.js index a2c23c218..b89d8b9ee 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -49,25 +49,7 @@ export const duration = { } }; -/** - * Helper to wait for log emission. - * @param {Object} _event The event to wait for. - */ -export function promisifyLogWatch(_event, _times) { - return new Promise((resolve, reject) => { - let i = 0; - _event.watch((error, log) => { - if (error !== null) reject(error); - i = i + 1; - console.log("Received event: " + i + " out of: " + _times); - if (i == _times) { - _event.stopWatching(); - resolve(log); - } - }); - }); -} - -export function latestBlock() { - return web3.eth.getBlock("latest").number; +export async function latestBlock() { + let block = await web3.eth.getBlock("latest"); + return block.number; } diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 179b571f1..7b62336bd 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -11,10 +11,10 @@ const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("Issuance", accounts => { +contract("Issuance", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_investor1; @@ -26,12 +26,12 @@ contract("Issuance", accounts => { let blockNo; let balanceOfReceiver; let message = "Transaction Should Fail!"; - const TM_Perm = "WHITELIST"; - const delegateDetails = "I am delegate"; + const TM_Perm = web3.utils.fromAscii("WHITELIST"); + const delegateDetails = web3.utils.fromAscii("I am delegate"); // investor Details - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); - let expiryTime = toTime + duration.days(100); + let fromTime; + let toTime; + let expiryTime; // Contract Instance Declaration let I_GeneralPermissionManagerFactory; @@ -65,23 +65,27 @@ contract("Issuance", accounts => { const stoKey = 3; const budget = 0; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(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 = web3.utils.toWei("1000"); + const cap = new BN(web3.utils.toWei("10000")); + const rate = new BN(web3.utils.toWei("1000")); const fundRaiseType = [0]; - const cappedSTOSetupCost = web3.utils.toWei("20000", "ether"); + const cappedSTOSetupCost = new BN(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 () => { + fromTime = await latestTime(); + toTime = await latestTime(); + expiryTime = toTime + duration.days(15); // Accounts setup account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -134,11 +138,9 @@ contract("Issuance", accounts => { }); 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.getTokens(new BN(10000).mul(new BN(10).pow(new BN(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); @@ -147,15 +149,15 @@ contract("Issuance", accounts => { it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { 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[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey); @@ -164,7 +166,7 @@ contract("Issuance", accounts => { it("POLYMATH: Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("POLYMATH: Should successfully attach the STO factory with the security token", async () => { @@ -173,8 +175,8 @@ contract("Issuance", accounts => { [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, cappedSTOSetupCost); let bytesSTO = encodeModuleCall(STOParameters, [ - latestTime() + duration.seconds(5000), - latestTime() + duration.days(30), + await latestTime() + duration.seconds(5000), + await latestTime() + duration.days(30), cap, rate, fundRaiseType, @@ -184,7 +186,7 @@ contract("Issuance", accounts => { 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 }); + const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: account_polymath }); assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal( @@ -192,14 +194,14 @@ contract("Issuance", accounts => { "CappedSTO", "CappedSTOFactory module was not added" ); - I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); + I_CappedSTO = await 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); + fromTime = await latestTime(); + toTime = await latestTime() + duration.days(15); expiryTime = toTime + duration.days(100); let tx = await I_GeneralTransferManager.modifyWhitelist( @@ -215,17 +217,21 @@ contract("Issuance", accounts => { 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("Should add the delegate with permission", async () => { + //First attach a permission manager to the token + await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(0), { from: account_polymath }); + let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; + I_GeneralPermissionManager = await 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 () => { @@ -238,7 +244,7 @@ contract("Issuance", accounts => { describe("Operations on the STO", async () => { it("Should Buy the tokens", async () => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); - blockNo = latestBlock(); + blockNo = await latestBlock(); // Jump time await increaseTime(5000); // Fallback transaction @@ -246,20 +252,20 @@ contract("Issuance", accounts => { from: account_investor1, to: I_CappedSTO.address, gas: 6100000, - value: web3.utils.toWei("1", "ether") + value: new BN(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.getRaised.call(0)).div(new BN(10).pow(new BN(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); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 1000); }); it("Verification of the event Token Purchase", async () => { - const log = await promisifyLogWatch(I_CappedSTO.TokenPurchase({ from: blockNo }), 1); + const log = (await I_CappedSTO.getPastEvents('TokenPurchase', {filter: {from: blockNo}}))[0]; 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"); + assert.equal(log.args.amount.div(new BN(10).pow(new BN(18))).toNumber(), 1000, "Wrong No. token get dilivered"); }); it("should add the investor into the whitelist by the delegate", async () => { @@ -275,14 +281,14 @@ contract("Issuance", accounts => { from: account_investor2, to: I_CappedSTO.address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(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.getRaised.call(0)).div(new BN(10).pow(new BN(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); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).div(new BN(10).pow(new BN(18))).toNumber(), 1000); }); }); }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 41fabbd46..7ac1bd4cf 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -3,7 +3,12 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from "./hel import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { setUpPolymathNetwork, deployManualApprovalTMAndVerifyed, deployGPMAndVerifyed, deployCountTMAndVerifyed } from "./helpers/createInstances"; +import { + setUpPolymathNetwork, + deployManualApprovalTMAndVerifyed, + deployGPMAndVerifyed, + deployCountTMAndVerifyed +} from "./helpers/createInstances"; const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); @@ -12,10 +17,10 @@ const CountTransferManager = artifacts.require("./CountTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("ManualApprovalTransferManager", accounts => { +contract("ManualApprovalTransferManager", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -26,11 +31,6 @@ contract("ManualApprovalTransferManager", accounts => { 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 @@ -70,12 +70,16 @@ contract("ManualApprovalTransferManager", accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -110,7 +114,11 @@ contract("ManualApprovalTransferManager", accounts => { // STEP 3: Deploy the ManualApprovalTransferManagerFactory [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 4: Deploy the Paid ManualApprovalTransferManagerFactory - [P_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); + [P_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed( + account_polymath, + I_MRProxied, + new BN(web3.utils.toWei("500", "ether")) + ); // STEP 5: Deploy the CountTransferManagerFactory [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); @@ -143,15 +151,15 @@ contract("ManualApprovalTransferManager", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -160,7 +168,7 @@ contract("ManualApprovalTransferManager", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -170,9 +178,9 @@ contract("ManualApprovalTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -190,9 +198,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, new BN(web3.utils.toWei("4", "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)).toString(), new BN(web3.utils.toWei("4", "ether")).toString()); }); it("Should Buy some more tokens", async () => { @@ -200,9 +208,9 @@ contract("ManualApprovalTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -217,15 +225,15 @@ 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, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -233,12 +241,12 @@ contract("ManualApprovalTransferManager", accounts => { 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 }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_ManualApprovalTransferManagerFactory.address, "0x", - web3.utils.toWei("500", "ether"), - 0, + new BN(web3.utils.toWei("500", "ether")), + new BN(0), { from: token_owner } ); assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); @@ -247,19 +255,19 @@ contract("ManualApprovalTransferManager", accounts => { "ManualApprovalTransferManager", "ManualApprovalTransferManagerFactory module was not added" ); - P_ManualApprovalTransferManagerFactory = ManualApprovalTransferManager.at(tx.logs[3].args._module); + P_ManualApprovalTransferManagerFactory = await 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 }); + const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "0x0", new BN(0), new BN(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); + I_ManualApprovalTransferManager = await 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 () => { @@ -267,8 +275,8 @@ contract("ManualApprovalTransferManager", accounts => { I_ManualApprovalTransferManager.verifyTransfer( account_investor4, account_investor4, - web3.utils.toWei("2", "ether"), - "", + new BN(web3.utils.toWei("2", "ether")), + "0x0", true, { from: token_owner } ) @@ -279,8 +287,8 @@ contract("ManualApprovalTransferManager", accounts => { await I_ManualApprovalTransferManager.verifyTransfer( account_investor4, account_investor4, - web3.utils.toWei("2", "ether"), - "", + new BN(web3.utils.toWei("2", "ether")), + "0x0", false, { from: token_owner } ); @@ -289,9 +297,9 @@ contract("ManualApprovalTransferManager", accounts => { it("Add a new token holder", async () => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -305,31 +313,31 @@ contract("ManualApprovalTransferManager", accounts => { "Failed in adding the investor in whitelist" ); // Pause at the transferManager level - await I_ManualApprovalTransferManager.pause({from: token_owner}); + 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, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); // Unpause at the transferManager level - await I_ManualApprovalTransferManager.unpause({from: token_owner}); + await I_ManualApprovalTransferManager.unpause({ from: token_owner }); }); 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(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)).toString(), new BN(web3.utils.toWei("5", "ether")).toString()); }); it("Should fail to add a manual approval because invalid _to address", async () => { await catchRevert( I_ManualApprovalTransferManager.addManualApproval( account_investor1, - "", - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + address_zero, + new BN(web3.utils.toWei("2", "ether")), + currentTime.add(new BN(duration.days(1))), { from: token_owner } ) ); @@ -340,7 +348,7 @@ contract("ManualApprovalTransferManager", accounts => { I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), + new BN(web3.utils.toWei("2", "ether")), 99999, { from: token_owner } ) @@ -351,18 +359,18 @@ contract("ManualApprovalTransferManager", accounts => { await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + new BN(web3.utils.toWei("2", "ether")), + currentTime.add(new BN(duration.days(1))), { from: token_owner } ); }); it("Add a manual approval for a 5th investor from issuance", async () => { await I_ManualApprovalTransferManager.addManualApproval( - "", + address_zero, account_investor5, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + new BN(web3.utils.toWei("2", "ether")), + currentTime.add(new BN(duration.days(1))), { from: token_owner } ); }); @@ -372,15 +380,15 @@ contract("ManualApprovalTransferManager", accounts => { I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(5), + new BN(web3.utils.toWei("2", "ether")), + currentTime.add(new BN(duration.days(5))), { 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 })); + await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, address_zero, { from: token_owner })); }); it("Should revoke manual approval", async () => { @@ -393,60 +401,59 @@ contract("ManualApprovalTransferManager", accounts => { await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + new BN(web3.utils.toWei("2", "ether")), + currentTime.add(new BN(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 }); + await I_SecurityToken.transfer(account_investor4, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Approval fails with wrong from to address", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor5, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + await catchRevert(I_SecurityToken.transfer(account_investor5, new BN(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")); + await I_SecurityToken.mint(account_investor5, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Check verifyTransfer without actually transferring", async () => { let verified = await I_SecurityToken.verifyTransfer.call( account_investor1, account_investor4, - web3.utils.toWei("1", "ether"), - "" + new BN(web3.utils.toWei("1", "ether")), + "0x0" ); - console.log(JSON.stringify(verified)); assert.equal(verified, true); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("2", "ether"), ""); + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, new BN(web3.utils.toWei("2", "ether")), "0x0"); assert.equal(verified, false); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("1", "ether"), ""); + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, new BN(web3.utils.toWei("1", "ether")), "0x0"); 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 }); + await I_SecurityToken.transfer(account_investor4, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Check further transfers fail", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + await catchRevert(I_SecurityToken.transfer(account_investor4, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); //Check that other transfers are still valid - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); + await I_SecurityToken.transfer(account_investor2, new BN(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), { + I_ManualApprovalTransferManager.addManualBlocking(account_investor1, address_zero, currentTime.add(new BN(duration.days(1))), { from: token_owner }) ); @@ -459,39 +466,41 @@ contract("ManualApprovalTransferManager", accounts => { }); it("Add a manual block for a 2nd investor", async () => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(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 }) + I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(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 })); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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 })); + await catchRevert(I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, address_zero, { 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")); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Check manual block ignored after expiry", async () => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(duration.days(1))), { from: token_owner }); - await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); }); it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { @@ -509,11 +518,11 @@ contract("ManualApprovalTransferManager", accounts => { [1] ); - const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, new BN(0), new BN(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); + I_CountTransferManager = await CountTransferManager.at(tx.logs[2].args._module); }); it("Should get the permission list", async () => { diff --git a/test/k_module_registry.js b/test/k_module_registry.js index ec58b28e9..1504d86b6 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -19,10 +19,10 @@ const TestSTOFactory = artifacts.require("./TestSTOFactory.sol"); const ReclaimTokens = artifacts.require("./ReclaimTokens.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("ModuleRegistry", accounts => { +contract("ModuleRegistry", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_investor1; @@ -34,9 +34,6 @@ contract("ModuleRegistry", accounts => { let account_temp; let balanceOfReceiver; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); let ID_snap; let message = "Transaction Should fail!"; @@ -80,9 +77,10 @@ contract("ModuleRegistry", accounts => { const stoKey = 3; const budget = 0; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); // delagate details const delegateDetails = "I am delegate .."; @@ -91,14 +89,16 @@ contract("ModuleRegistry", accounts => { // Capped STO details let startTime; let endTime; - const cap = web3.utils.toWei("10000"); + const cap = new BN(web3.utils.toWei("10000")); const rate = 1000; const fundRaiseType = [0]; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; const MRProxyParameters = ["address", "address"]; + let currentTime; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; account_investor1 = accounts[9]; @@ -146,10 +146,7 @@ contract("ModuleRegistry", accounts => { describe("Test the initialize the function", async () => { it("Should successfully update the implementation address -- fail because polymathRegistry address is 0x", async () => { - let bytesProxy = encodeProxyCall(MRProxyParameters, [ - address_zero, - account_polymath - ]); + let bytesProxy = encodeProxyCall(MRProxyParameters, [address_zero, account_polymath]); catchRevert( I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { from: account_polymath @@ -159,10 +156,7 @@ contract("ModuleRegistry", accounts => { }); it("Should successfully update the implementation address -- fail because owner address is 0x", async () => { - let bytesProxy = encodeProxyCall(MRProxyParameters, [ - I_PolymathRegistry.address, - address_zero - ]); + let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, address_zero]); catchRevert( I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { from: account_polymath @@ -172,10 +166,7 @@ contract("ModuleRegistry", accounts => { }); it("Should successfully update the implementation address -- fail because all params are 0x", async () => { - let bytesProxy = encodeProxyCall(MRProxyParameters, [ - address_zero, - address_zero - ]); + let bytesProxy = encodeProxyCall(MRProxyParameters, [address_zero, address_zero]); catchRevert( I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { from: account_polymath @@ -184,15 +175,12 @@ contract("ModuleRegistry", accounts => { ); }); - it("Should successfully update the implementation address", async() => { - let bytesProxy = encodeProxyCall(MRProxyParameters, [ - I_PolymathRegistry.address, - account_polymath - ]); + it("Should successfully update the implementation address", async () => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { from: account_polymath }); I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, { from: account_polymath }); - }) + }); }); describe("Test cases for the ModuleRegistry", async () => { @@ -265,25 +253,21 @@ contract("ModuleRegistry", accounts => { }); it("Should fail in registering the module-- type = 0", async () => { - I_MockFactory = await MockFactory.new(0, 0, 0, 0, { from: account_polymath }); + I_MockFactory = await MockFactory.new(new BN(0), new BN(0), new BN(0), address_zero, { from: account_polymath }); catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); }); it("Should fail to register the new module because msg.sender is not the owner of the module", async() => { - I_CappedSTOLogic = await CappedSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - I_CappedSTOFactory3 = await CappedSTOFactory.new(0, 0, 0, I_CappedSTOLogic.address, { from: account_temp }); - catchRevert( - I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: token_owner }) - ); + I_CappedSTOLogic = await CappedSTO.new(address_zero, address_zero, { from: account_polymath }); + I_CappedSTOFactory3 = await CappedSTOFactory.new(new BN(0), new BN(0), new BN(0), I_CappedSTOLogic.address, { from: account_temp }); + catchRevert(I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: token_owner })); }); - it("Should successfully register the module -- fail because no module type uniqueness", async() => { - await I_MockFactory.changeTypes({from: account_polymath }); - catchRevert( - I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }) - ); - }) + it("Should successfully register the module -- fail because no module type uniqueness", async () => { + await I_MockFactory.changeTypes({ from: account_polymath }); + catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); + }); }); describe("Test case for verifyModule", async () => { @@ -298,7 +282,7 @@ contract("ModuleRegistry", accounts => { }); it("Should successfully verify the module -- false", async () => { - I_CappedSTOFactory1 = await CappedSTOFactory.new(0, 0, 0, I_CappedSTOLogic.address, { from: account_polymath }); + I_CappedSTOFactory1 = await CappedSTOFactory.new(new BN(0), new BN(0), new BN(0), I_CappedSTOLogic.address, { 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"); @@ -312,30 +296,26 @@ contract("ModuleRegistry", accounts => { 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_PolyToken.getTokens(new BN(web3.utils.toWei("500")), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, new BN(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[2].args._ticker, symbol.toUpperCase()); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); }); it("Should fail in adding module. Because module is un-verified", async () => { - startTime = latestTime() + duration.seconds(5000); + startTime = await latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - await catchRevert(I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner })); + await catchRevert(I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); }); it("Should fail to register module because custom modules not allowed", async () => { - I_CappedSTOFactory2 = await CappedSTOFactory.new(0, 0, 0, I_CappedSTOLogic.address, { from: token_owner }); + I_CappedSTOFactory2 = await CappedSTOFactory.new(0, new BN(0), new BN(0), I_CappedSTOLogic.address, { from: token_owner }); - assert.notEqual( - I_CappedSTOFactory2.address.valueOf(), - address_zero, - "CappedSTOFactory contract was not deployed" - ); + assert.notEqual(I_CappedSTOFactory2.address.valueOf(), address_zero, "CappedSTOFactory contract was not deployed"); await catchRevert(I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner })); }); @@ -355,11 +335,11 @@ contract("ModuleRegistry", accounts => { }); it("Should successfully add module because custom modules switched on", async () => { - startTime = latestTime() + duration.seconds(5000); + startTime = await 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 }); + tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, new BN(0), new BN(0), { from: token_owner }); assert.equal(tx.logs[2].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal( @@ -371,29 +351,27 @@ contract("ModuleRegistry", accounts => { assert.equal(_reputation.length, 1); }); - it("Should successfully add module when custom modules switched on -- fail because factory owner is different", async() => { - await I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: account_temp }) - startTime = latestTime() + duration.seconds(5000); + it("Should successfully add module when custom modules switched on -- fail because factory owner is different", async () => { + await I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: account_temp }); + startTime = await latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - catchRevert( - I_SecurityToken.addModule(I_CappedSTOFactory3.address, bytesSTO, 0, 0, { from: token_owner }) - ); - }) + catchRevert(I_SecurityToken.addModule(I_CappedSTOFactory3.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); + }); it("Should successfully add verified module", async () => { I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(0, 0, 0, I_GeneralPermissionManagerLogic.address, { + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(0, new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, { 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 }); + let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(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(0, 0, 0, 0, { from: account_polymath }); + I_TestSTOFactory = await TestSTOFactory.new(new BN(0), new BN(0), new BN(0), address_zero, { 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 @@ -404,35 +382,35 @@ contract("ModuleRegistry", accounts => { assert.equal(_lstVersion[1], 1); let bytesData = encodeModuleCall( ["uint256", "uint256", "uint256", "string"], - [latestTime(), latestTime() + duration.days(1), cap, "Test STO"] + [await latestTime(), currentTime.add(new BN(duration.days(1))), cap, "Test STO"] ); - await catchRevert(I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner })); + await catchRevert(I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, new BN(0), new BN(0), { from: token_owner })); 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 }); + await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0, new BN(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, 2, 0, 1); + await I_STRProxied.setProtocolVersion(I_STFactory.address, 2, new BN(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_PolyToken.getTokens(new BN(web3.utils.toWei("500")), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, new BN(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[2].args._ticker, newSymbol.toUpperCase()); - I_SecurityToken2 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken2 = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); let bytesData = encodeModuleCall( ["uint256", "uint256", "uint256", "string"], - [latestTime(), latestTime() + duration.days(1), cap, "Test STO"] + [await latestTime(), currentTime.add(new BN(duration.days(1))), cap, "Test STO"] ); - await catchRevert(I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner })); + await catchRevert(I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, new BN(0), new BN(0), { from: token_owner })); }); }); @@ -542,28 +520,23 @@ contract("ModuleRegistry", accounts => { describe("Test cases for IRegistry functionality", async () => { describe("Test cases for reclaiming funds", async () => { - - it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { - await I_PolyToken.transfer(I_MRProxied.address, web3.utils.toWei("1"), { from: token_owner }); - catchRevert( - I_MRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) - ); + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async () => { + await I_PolyToken.transfer(I_MRProxied.address, new BN(web3.utils.toWei("1")), { from: token_owner }); + catchRevert(I_MRProxied.reclaimERC20(address_zero, { from: account_polymath })); }); - it("Should successfully reclaim POLY tokens -- not authorised", async() => { - catchRevert( - I_MRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) - ); + it("Should successfully reclaim POLY tokens -- not authorised", async () => { + catchRevert(I_MRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp })); }); it("Should successfully reclaim POLY tokens", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); + await I_PolyToken.getTokens(new BN(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() + bal2.div(new BN(10).pow(new BN(18))).toNumber(), + bal2.div(new BN(10).pow(new BN(18))).toNumber() ); }); }); @@ -590,76 +563,61 @@ contract("ModuleRegistry", accounts => { }); }); - describe("Test cases for the ReclaimTokens contract", async() => { - - it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { + describe("Test cases for the ReclaimTokens contract", async () => { + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async () => { I_ReclaimERC20 = await ReclaimTokens.at(I_FeatureRegistry.address); - await I_PolyToken.transfer(I_ReclaimERC20.address, web3.utils.toWei("1"), { from: token_owner }); - catchRevert( - I_ReclaimERC20.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) - ); + await I_PolyToken.transfer(I_ReclaimERC20.address, new BN(web3.utils.toWei("1")), { from: token_owner }); + catchRevert(I_ReclaimERC20.reclaimERC20(address_zero, { from: account_polymath })); }); - it("Should successfully reclaim POLY tokens -- not authorised", async() => { - catchRevert( - I_ReclaimERC20.reclaimERC20(I_PolyToken.address, { from: account_temp }) - ); + it("Should successfully reclaim POLY tokens -- not authorised", async () => { + catchRevert(I_ReclaimERC20.reclaimERC20(I_PolyToken.address, { from: account_temp })); }); it("Should successfully reclaim POLY tokens", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("1"), I_ReclaimERC20.address); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1")), I_ReclaimERC20.address); let bal1 = await I_PolyToken.balanceOf.call(account_polymath); await I_ReclaimERC20.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() + bal2.div(new BN(10).pow(new BN(18))).toNumber(), + bal2.div(new BN(10).pow(new BN(18))).toNumber() ); }); - }) - - describe("Test case for the PolymathRegistry", async() => { + }); - it("Should successfully get the address -- fail because key is not exist", async() => { - catchRevert( - I_PolymathRegistry.getAddress("PolyOracle") - ); + describe("Test case for the PolymathRegistry", async () => { + it("Should successfully get the address -- fail because key is not exist", async () => { + catchRevert(I_PolymathRegistry.getAddress("PolyOracle")); }); - it("Should successfully get the address", async() => { + it("Should successfully get the address", async () => { let _moduleR = await I_PolymathRegistry.getAddress("ModuleRegistry"); assert.equal(_moduleR, I_ModuleRegistryProxy.address); - }) - }) - - - describe("Test cases for the transferOwnership", async() => { + }); + }); - it("Should fail to transfer the ownership -- not authorised", async() => { - catchRevert( - I_MRProxied.transferOwnership(account_temp, { from: account_issuer}) - ); + describe("Test cases for the transferOwnership", async () => { + it("Should fail to transfer the ownership -- not authorised", async () => { + catchRevert(I_MRProxied.transferOwnership(account_temp, { from: account_issuer })); }); - it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { - catchRevert( - I_MRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) - ); + it("Should fail to transfer the ownership -- 0x address is not allowed", async () => { + catchRevert(I_MRProxied.transferOwnership(address_zero, { from: account_polymath })); }); - it("Should successfully transfer the ownership of the STR", async() => { + it("Should successfully transfer the ownership of the STR", async () => { let tx = await I_MRProxied.transferOwnership(account_temp, { from: account_polymath }); assert.equal(tx.logs[0].args.previousOwner, account_polymath); assert.equal(tx.logs[0].args.newOwner, account_temp); }); - it("New owner has authorisation", async() => { + it("New owner has authorisation", async () => { let tx = await I_MRProxied.transferOwnership(account_polymath, { from: account_temp }); assert.equal(tx.logs[0].args.previousOwner, account_temp); assert.equal(tx.logs[0].args.newOwner, account_polymath); }); - - }) + }); }); }); }); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index c3d08ba58..f98e2c41f 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -10,10 +10,10 @@ const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager") const SecurityToken = artifacts.require("./SecurityToken.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("PercentageTransferManager", accounts => { +contract("PercentageTransferManager", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -24,11 +24,6 @@ contract("PercentageTransferManager", accounts => { let account_investor4; let account_delegate; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime(); - let expiryTime = toTime + duration.days(15); - let message = "Transaction Should Fail!"; // Contract Instance Declaration @@ -59,7 +54,8 @@ 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"; + const managerDetails = web3.utils.fromAscii("Hello"); + const delegateDetails = web3.utils.fromAscii("I am delegate"); // Module key const delegateManagerKey = 1; @@ -67,26 +63,35 @@ contract("PercentageTransferManager", accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(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]); - - before(async() => { - // Accounts setup + 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] + ); + + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; + + before(async () => { + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -95,6 +100,7 @@ contract("PercentageTransferManager", accounts => { account_investor1 = accounts[7]; account_investor2 = accounts[8]; account_investor3 = accounts[9]; + account_investor4 = accounts[5] account_delegate = accounts[6]; let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -121,7 +127,11 @@ contract("PercentageTransferManager", accounts => { [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, 0); // STEP 4(b): Deploy the PercentageTransferManager - [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); + [P_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified( + account_polymath, + I_MRProxied, + new BN(web3.utils.toWei("500", "ether")) + ); // Printing all the contract addresses console.log(` @@ -152,15 +162,15 @@ contract("PercentageTransferManager", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -169,20 +179,19 @@ contract("PercentageTransferManager", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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 }); + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", new BN(0), new BN(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); + I_GeneralPermissionManager = await GeneralPermissionManager.at(tx.logs[2].args._module); }); - }); describe("Buy tokens using on-chain whitelist", async () => { @@ -191,9 +200,9 @@ contract("PercentageTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -211,9 +220,9 @@ contract("PercentageTransferManager", 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should Buy some more tokens", async () => { @@ -221,9 +230,9 @@ contract("PercentageTransferManager", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -238,15 +247,15 @@ contract("PercentageTransferManager", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should successfully attach the PercentageTransferManager factory with the security token - failed payment", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -254,12 +263,12 @@ contract("PercentageTransferManager", accounts => { 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 }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_PercentageTransferManagerFactory.address, bytesSTO, - web3.utils.toWei("500", "ether"), - 0, + new BN(web3.utils.toWei("500", "ether")), + new BN(0), { from: token_owner } ); assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); @@ -268,27 +277,27 @@ contract("PercentageTransferManager", accounts => { "PercentageTransferManager", "PercentageTransferManagerFactory module was not added" ); - P_PercentageTransferManager = PercentageTransferManager.at(tx.logs[3].args._module); + P_PercentageTransferManager = await 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 }); + const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, new BN(0), new BN(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); + I_PercentageTransferManager = await 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), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), true, { from: account_issuer, @@ -304,9 +313,9 @@ contract("PercentageTransferManager", accounts => { // 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, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should pause the tranfers at transferManager level", async () => { @@ -316,9 +325,9 @@ contract("PercentageTransferManager", accounts => { 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Should unpause the tranfers at transferManager level", async () => { @@ -326,48 +335,42 @@ contract("PercentageTransferManager", accounts => { }); it("Should not be able to transfer between existing token holders over limit", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor1 })); + await catchRevert(I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("2", "ether")), { from: account_investor1 })); }); - it("Should not be able to mint token amount over limit", async() => { - await catchRevert(I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner })) + it("Should not be able to mint token amount over limit", async () => { + await catchRevert(I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("100", "ether")), { from: token_owner })); }); - it("Allow unlimited primary issuance and remint", async() => { + 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 I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("100", "ether")), { from: token_owner }); // trying to call it again with the same value. should fail - await catchRevert( - I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }) - ) + await catchRevert(I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner })); await revertToSnapshot(snapId); }); - it("Should not be able to transfer between existing token holders over limit", async() => { - await catchRevert( - I_SecurityToken.transfer(account_investor3, web3.utils.toWei('2', 'ether'), { from: account_investor1 }) - ) + it("Should not be able to transfer between existing token holders over limit", async () => { + await catchRevert(I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("2", "ether")), { from: account_investor1 })); }); 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 }) - ) + await catchRevert(I_PercentageTransferManager.changeHolderPercentage(new BN(10).pow(new BN(18)), { from: account_delegate })); }); - it("Should successfully add the delegate", async() => { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}); + 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() => { + it("Should provide the permission", async () => { let tx = await I_GeneralPermissionManager.changePermission( account_delegate, I_PercentageTransferManager.address, - "ADMIN", + web3.utils.fromAscii("ADMIN"), true, - {from: token_owner} + { from: token_owner } ); assert.equal(tx.logs[0].args._delegate, account_delegate); }); @@ -375,32 +378,38 @@ contract("PercentageTransferManager", accounts => { 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: account_delegate }); + await I_PercentageTransferManager.changeHolderPercentage(new BN(10).pow(new BN(18)), { from: account_delegate }); - assert.equal((await I_PercentageTransferManager.maxHolderPercentage()).toNumber(), 100 * 10 ** 16); + assert.equal((await I_PercentageTransferManager.maxHolderPercentage()).toString(), (new BN(10).pow(new BN(18))).toString()); }); 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 }); + await I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("2", "ether")), { from: account_investor1 }); }); - it("Should whitelist in batch --failed because of mismatch in array lengths", async() => { + it("Should whitelist in batch --failed because of mismatch in array lengths", async () => { + let addressArray = [account_investor3, account_investor4]; await catchRevert( - I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false], { from: token_owner }) + I_PercentageTransferManager.modifyWhitelistMulti(addressArray, [false], { from: token_owner }) ); - }) + }); - it("Should whitelist in batch", async() => { + it("Should whitelist in batch", async () => { let snapId = await takeSnapshot(); - await I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false, true], { from: token_owner }); + let addressArray = []; + addressArray.push(account_investor3); + addressArray.push(account_investor4); + await I_PercentageTransferManager.modifyWhitelistMulti(addressArray, [false, true], { + from: token_owner + }); await revertToSnapshot(snapId); - }) + }); 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.changeHolderPercentage(new BN(30).mul(new BN(10).pow(new BN(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 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor3 }); }); it("Should get the permission", async () => { diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 696ec92a1..daa982397 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.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 { setUpPolymathNetwork, deployPresaleSTOAndVerified } from "./helpers/createInstances" +import { setUpPolymathNetwork, deployPresaleSTOAndVerified } from "./helpers/createInstances"; const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PreSaleSTO = artifacts.require("./PreSaleSTO.sol"); @@ -11,10 +11,10 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("PreSaleSTO", accounts => { +contract("PreSaleSTO", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_investor1; @@ -69,13 +69,16 @@ contract("PreSaleSTO", accounts => { const budget = 0; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); let endTime; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; const STOParameters = ["uint256"]; + let currentTime; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; account_investor1 = accounts[4]; @@ -134,15 +137,15 @@ contract("PreSaleSTO", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey); @@ -151,21 +154,23 @@ contract("PreSaleSTO", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should fail to launch the STO due to endTime is 0", async () => { let bytesSTO = encodeModuleCall(STOParameters, [0]); - await catchRevert(I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner })); + await catchRevert(I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); }); it("Should successfully attach the Paid STO factory with the security token", async () => { let snap_id = await takeSnapshot(); - endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time + endTime = await latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time let bytesSTO = encodeModuleCall(STOParameters, [endTime]); - await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(P_PreSaleSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: token_owner }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_PreSaleSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + from: token_owner + }); assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); assert.equal( @@ -173,23 +178,21 @@ contract("PreSaleSTO", accounts => { "PreSaleSTO", "PreSaleSTOFactory module was not added" ); - I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); + I_PreSaleSTO = await PreSaleSTO.at(tx.logs[2].args._module); await revertToSnapshot(snap_id); }); it("Should successfully attach the STO factory with the security token -- fail because signature is different", async () => { - endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time + endTime = await latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time let bytesSTO = encodeModuleCall(["string"], ["hey"]); - await catchRevert( - I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }) - ); + await catchRevert(I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); }); 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 + endTime = await 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 }); + const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner }); assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); assert.equal( @@ -197,14 +200,14 @@ contract("PreSaleSTO", accounts => { "PreSaleSTO", "PreSaleSTOFactory module was not added" ); - I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); + I_PreSaleSTO = await PreSaleSTO.at(tx.logs[2].args._module); }); 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 + endTime = await 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 }); + const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner }); assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); assert.equal( @@ -212,7 +215,7 @@ contract("PreSaleSTO", accounts => { "PreSaleSTO", "PreSaleSTOFactory module was not added" ); - I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); + I_PreSaleSTO = await PreSaleSTO.at(tx.logs[2].args._module); }); }); @@ -229,11 +232,11 @@ contract("PreSaleSTO", accounts => { describe("Buy tokens", async () => { it("Should allocate the tokens -- failed due to investor not on whitelist", async () => { - await catchRevert(I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei("1", "ether"), 0)); + await catchRevert(I_PreSaleSTO.allocateTokens(account_investor1, 1000, new BN(web3.utils.toWei("1", "ether")), 0)); }); it("Should Buy the tokens", async () => { - fromTime = latestTime(); + fromTime = await latestTime(); toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); @@ -247,34 +250,34 @@ contract("PreSaleSTO", accounts => { // Jump time await increaseTime(duration.days(1)); - await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether"), 0, { + await I_PreSaleSTO.allocateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether")), new BN(0), { from: account_issuer }); - assert.equal((await I_PreSaleSTO.getRaised.call(0)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); + assert.equal((await I_PreSaleSTO.getRaised.call(0)).div(new BN(10).pow(new BN(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 because of amount is 0", async() => { + it("Should allocate the tokens --failed because of amount is 0", async () => { await catchRevert( - I_PreSaleSTO.allocateTokens(account_investor1, 0, web3.utils.toWei("1", "ether"), 0, { + I_PreSaleSTO.allocateTokens(account_investor1, new BN(0), new BN(web3.utils.toWei("1", "ether")), new BN(0), { from: account_issuer }) ); - }) + }); it("Should allocate the tokens -- failed due to msg.sender is not pre sale admin", async () => { await catchRevert( - I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether"), 0, { + I_PreSaleSTO.allocateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether")), new BN(0), { from: account_fundsReceiver }) ); }); it("Should allocate tokens to multiple investors", async () => { - fromTime = latestTime(); + fromTime = await latestTime(); toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); @@ -296,82 +299,84 @@ contract("PreSaleSTO", accounts => { await I_PreSaleSTO.allocateTokensMulti( [account_investor2, account_investor3], - [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether"))], [0, 0], - [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + [new BN(web3.utils.toWei("1000", "ether")), new BN(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.getRaised.call(1)).div(new BN(10).pow(new BN(18))).toNumber(), 2000); assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); }); - it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + it("Should successfully mint multiple tokens -- failed because array mismatch", async () => { await catchRevert( I_PreSaleSTO.allocateTokensMulti( [account_investor2], - [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether"))], [0, 0], - [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + [new BN(web3.utils.toWei("1000", "ether")), new BN(web3.utils.toWei("1000", "ether"))], { from: account_issuer } ) ); - }) + }); - it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + it("Should successfully mint multiple tokens -- failed because array mismatch", async () => { await catchRevert( I_PreSaleSTO.allocateTokensMulti( [account_investor2, account_investor3], - [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether"))], [0], - [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + [new BN(web3.utils.toWei("1000", "ether")), new BN(web3.utils.toWei("1000", "ether"))], { from: account_issuer } ) ); }); - it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + it("Should successfully mint multiple tokens -- failed because array mismatch", async () => { await catchRevert( I_PreSaleSTO.allocateTokensMulti( [account_investor2, account_investor3], - [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], - [0,0], - [web3.utils.toWei("1000", "ether")], + [new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether"))], + [0, 0], + [new BN(web3.utils.toWei("1000", "ether"))], { from: account_issuer } ) ); }); - it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + it("Should successfully mint multiple tokens -- failed because array mismatch", async () => { await catchRevert( I_PreSaleSTO.allocateTokensMulti( [account_investor2, account_investor3], - [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [new BN(web3.utils.toWei("1", "ether")), new BN(web3.utils.toWei("1", "ether"))], [0], - [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + [new BN(web3.utils.toWei("1000", "ether")), new BN(web3.utils.toWei("1000", "ether"))], { from: account_issuer } ) ); }); - it("Should buy some more tokens to previous investor", async() => { - await I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei("1000", "ether"), web3.utils.toWei("1", "ether"), 0, { from: account_issuer }); + it("Should buy some more tokens to previous investor", async () => { + await I_PreSaleSTO.allocateTokens(account_investor1, new BN(web3.utils.toWei("1000", "ether")), new BN(web3.utils.toWei("1", "ether")), new BN(0), { + from: account_issuer + }); // No change in the investor count assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); - }) + }); it("Should failed at the time of buying the tokens -- Because STO has ended", async () => { await increaseTime(duration.days(100)); // increased beyond the end time of the STO await catchRevert( - I_PreSaleSTO.allocateTokens(account_investor1, 1000, web3.utils.toWei("1", "ether"), 0, { from: account_issuer }) + I_PreSaleSTO.allocateTokens(account_investor1, 1000, new BN(web3.utils.toWei("1", "ether")), new BN(0), { from: account_issuer }) ); }); }); 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"); + let value = new BN(web3.utils.toWei("100", "ether")); await I_PolyToken.getTokens(value, account_investor1); await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); @@ -379,7 +384,7 @@ contract("PreSaleSTO", accounts => { }); it("Should successfully reclaim POLY", async () => { - let value = web3.utils.toWei("100", "ether"); + let value = new BN(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); @@ -388,29 +393,29 @@ contract("PreSaleSTO", accounts => { 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(), + (await I_PolyToken.balanceOf(account_investor1)).toString(), + initInvestorBalance.sub(value).toString(), "tokens are not transferred out from investor account" ); assert.equal( - (await I_PolyToken.balanceOf(token_owner)).toNumber(), + (await I_PolyToken.balanceOf(token_owner)).toString(), initOwnerBalance .add(value) .add(initContractBalance) - .toNumber(), + .toString(), "tokens are not added to the owner account" ); assert.equal( (await I_PolyToken.balanceOf(I_PreSaleSTO.address)).toNumber(), - 0, + new BN(0).toNumber(), "tokens are not trandfered out from STO contract" ); }); - it("Should get the the tokens sold", async() => { + it("Should get the the tokens sold", async () => { let _tokensSold = await I_PreSaleSTO.getTokensSold.call(); console.log(_tokensSold); - }) + }); }); describe("Test cases for the PresaleSTOFactory", async () => { diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index c8210a786..05955cb71 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -13,12 +13,11 @@ const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock const STFactory = artifacts.require("./STFactory.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); - const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("SecurityTokenRegistry", accounts => { +contract("SecurityTokenRegistry", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_investor1; @@ -31,9 +30,6 @@ contract("SecurityTokenRegistry", accounts => { let dummy_token; let balanceOfReceiver; - // investor Details - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(100); let ID_snap; const message = "Transaction Should Fail!!"; @@ -74,6 +70,7 @@ contract("SecurityTokenRegistry", accounts => { const symbol2 = "DET2"; const tokenDetails2 = "This is equity type of issuance"; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // Module key const permissionManagerKey = 1; @@ -82,18 +79,20 @@ contract("SecurityTokenRegistry", accounts => { 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 initRegFee = new BN(web3.utils.toWei("250")); + const newRegFee = new BN(web3.utils.toWei("300")); const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; const STOParameters = ["uint256", "uint256", "uint256", "string"]; // Capped STO details - const cap = web3.utils.toWei("10000"); + const cap = new BN(web3.utils.toWei("10000")); const someString = "Hello string"; + let currentTime; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; account_investor1 = accounts[9]; @@ -199,7 +198,7 @@ contract("SecurityTokenRegistry", accounts => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, I_STFactory.address, - 0, + new BN(0), initRegFee, account_polymath, I_STRGetter.address @@ -217,7 +216,7 @@ contract("SecurityTokenRegistry", accounts => { I_PolymathRegistry.address, I_STFactory.address, initRegFee, - 0, + new BN(0), account_polymath, I_STRGetter.address ]); @@ -247,14 +246,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should successfully update the implementation address -- fail because all params get 0", async () => { - let bytesProxy = encodeProxyCall(STRProxyParameters, [ - address_zero, - address_zero, - 0, - 0, - address_zero, - address_zero - ]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [address_zero, address_zero, new BN(0), new BN(0), address_zero, address_zero]); await catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath @@ -275,8 +267,8 @@ contract("SecurityTokenRegistry", accounts => { await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { from: account_polymath }); - I_Getter = STRGetter.at(I_SecurityTokenRegistryProxy.address); - I_STRProxied = SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + I_Getter = await STRGetter.at(I_SecurityTokenRegistryProxy.address); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); }); }); @@ -292,10 +284,10 @@ contract("SecurityTokenRegistry", accounts => { 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"); + assert.equal(stlaunchFee.toString(), initRegFee.toString(), "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"); + assert.equal(tickerRegFee.toString(), tickerRegFee.toString(), "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"); @@ -362,14 +354,14 @@ contract("SecurityTokenRegistry", accounts => { assert.equal(data[3], ""); }); - it("Should register the ticker when the tickerRegFee is 0", async() => { + it("Should register the ticker when the tickerRegFee is 0", async () => { let snap_Id = await takeSnapshot(); await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); let tx = await I_STRProxied.registerTicker(account_temp, "ZERO", 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, "ZERO", `Symbol should be ZERO`); await revertToSnapshot(snap_Id); - }) + }); it("Should fail to register same symbol again", async () => { // Give POLY to token issuer @@ -467,7 +459,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should fail to generate new security token if fee not provided", async () => { - await I_PolyToken.approve(I_STRProxied.address, 0, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(0), { from: token_owner }); await catchRevert( I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }), @@ -489,7 +481,7 @@ contract("SecurityTokenRegistry", accounts => { await I_STRProxied.unpause({ from: account_polymath }); await catchRevert( - I_STRProxied.generateSecurityToken(name, "", tokenDetails, false, { from: token_owner }), + I_STRProxied.generateSecurityToken(name, "0x0", tokenDetails, false, { from: token_owner }), "tx revert -> Zero ticker length is not allowed" ); }); @@ -509,15 +501,15 @@ contract("SecurityTokenRegistry", accounts => { }); 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[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTrasnferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); @@ -531,9 +523,9 @@ contract("SecurityTokenRegistry", accounts => { ); }); - it("Should fail to generate the SecurityToken because ticker gets expired", async() => { + it("Should fail to generate the SecurityToken because ticker gets expired", async () => { let snap_Id = await takeSnapshot(); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: token_owner }); let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); await increaseTime(duration.days(65)); await catchRevert( @@ -543,13 +535,13 @@ contract("SecurityTokenRegistry", accounts => { await revertToSnapshot(snap_Id); }); - it("Should generate the SecurityToken when launch fee is 0", async() => { + it("Should generate the SecurityToken when launch fee is 0", async () => { let snap_Id = await takeSnapshot(); await I_STRProxied.changeSecurityLaunchFee(0, { from: account_polymath }); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: token_owner }); let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); await I_STRProxied.generateSecurityToken(name, "CCC", tokenDetails, false, { from: token_owner }), - await revertToSnapshot(snap_Id); + await revertToSnapshot(snap_Id); }); it("Should get all created security tokens", async() => { @@ -562,11 +554,11 @@ contract("SecurityTokenRegistry", accounts => { // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, "TMP", "SecurityToken doesn't get deployed"); - let securityTokenTmp = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + let securityTokenTmp = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); let tokens = await I_Getter.getTokensByOwner.call(token_owner); - assert.equal(tokens.length, 1); - assert.equal(tokens[0], I_SecurityToken.address); + assert.equal(tokens.length, 1, "tokens array length error"); + assert.equal(tokens[0], I_SecurityToken.address, "ST address incorrect"); let allTokens = await I_Getter.getTokens.call(); assert.equal(allTokens.length, 2); @@ -588,7 +580,7 @@ contract("SecurityTokenRegistry", accounts => { address_zero, "STFactory002 contract was not deployed" ); - await I_STRProxied.setProtocolVersion(I_STFactory002.address, 2, 2, 0, { from: account_polymath }); + await I_STRProxied.setProtocolVersion(I_STFactory002.address, new BN(2), new BN(2), new BN(0), { from: account_polymath }); let _protocol = await I_Getter.getProtocolVersion.call(); assert.equal(_protocol[0], 2); assert.equal(_protocol[1], 2); @@ -604,18 +596,14 @@ contract("SecurityTokenRegistry", accounts => { 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[2].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - I_SecurityToken002 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); - let tokens = await I_Getter.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); + I_SecurityToken002 = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + const log = (await I_SecurityToken002.getPastEvents('ModuleAdded'))[0]; // 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"); @@ -625,17 +613,13 @@ contract("SecurityTokenRegistry", accounts => { 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(), - address_zero, - "SecurityTokenRegistry contract was not deployed" - ); + assert.notEqual(I_SecurityTokenRegistryV2.address.valueOf(), address_zero, "SecurityTokenRegistry contract was not deployed"); }); it("Should fail to upgrade the logic contract of the STRProxy -- bad owner", async () => { await I_STRProxied.pause({ from: account_polymath }); - catchRevert( + await catchRevert( I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", I_SecurityTokenRegistryV2.address, { from: account_temp }), "tx revert -> bad owner" ); @@ -663,25 +647,25 @@ contract("SecurityTokenRegistry", accounts => { describe("Generate custom tokens", async () => { it("Should fail if msg.sender is not polymath", async () => { await catchRevert( - I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), { + I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", currentTime, { from: account_delegate }), "tx revert -> msg.sender is not polymath account" ); }); - it("Should fail to genrate the custom security token -- ticker length is greater than 10 chars", async() => { + it("Should fail to genrate the custom security token -- ticker length is greater than 10 chars", async () => { await catchRevert( - I_STRProxied.modifySecurityToken("LOGAN", "LOGLOGLOGLOG", account_temp, dummy_token, "I am custom ST", latestTime(), { + I_STRProxied.modifySecurityToken("LOGAN", "LOGLOGLOGLOG", account_temp, dummy_token, "I am custom ST", currentTime, { from: account_polymath }), - "tx revert -> msg.sender is not polymath account" + "tx revert -> ticker length is greater than 10 chars" ); - }) + }); it("Should fail to generate the custom security token -- name should not be 0 length ", async () => { await catchRevert( - I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), { + I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", currentTime, { from: account_polymath }), "tx revert -> name should not be 0 length" @@ -690,7 +674,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail if ST address is 0 address", async () => { await catchRevert( - I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, 0, "I am custom ST", latestTime(), { + I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, address_zero, "I am custom ST", currentTime, { from: account_polymath }), "tx revert -> Security token address is 0" @@ -699,7 +683,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail if symbol length is 0", async () => { await catchRevert( - I_STRProxied.modifySecurityToken("", "", account_temp, dummy_token, "I am custom ST", latestTime(), { + I_STRProxied.modifySecurityToken("", "0x0", account_temp, dummy_token, "I am custom ST", currentTime, { from: account_polymath }), "tx revert -> zero length of the symbol is not allowed" @@ -708,14 +692,14 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail to generate the custom ST -- deployedAt param is 0", async () => { await catchRevert( - I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", 0, { from: account_polymath }), + I_STRProxied.modifySecurityToken(name2, symbol2, token_owner, dummy_token, "I am custom ST", new BN(0), { from: account_polymath }), "tx revert -> because deployedAt param is 0" ); }); 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.getTokens(new BN(web3.utils.toWei("1000")), account_temp); await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp }); let tickersListArray = await I_Getter.getTickersByOwner.call(account_temp); console.log(tickersListArray); @@ -723,7 +707,7 @@ contract("SecurityTokenRegistry", accounts => { tickersListArray = await I_Getter.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(), { + let tx = await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", currentTime, { from: account_polymath }); tickersListArray = await I_Getter.getTickersByOwner.call(account_temp); @@ -742,10 +726,10 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully generate the custom token", async () => { // Fulfilling the TickerStatus.NN condition // - // await catchRevert(I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath})); - // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); + // await catchRevert(I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", await latestTime(), {from: account_polymath})); + // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", await latestTime(), currentTime.add(new BN(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(), { + let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", currentTime, { from: account_polymath }); assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); @@ -761,17 +745,26 @@ contract("SecurityTokenRegistry", accounts => { assert.equal(symbolDetails[3], "LOGAN2", `Name of the symbol should be LOGAN`); }); - it("Should successfully modify the ticker", async() => { + it("Should successfully modify the ticker", async () => { let snap_Id = await takeSnapshot(); - let tx = await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(60), false, {from: account_polymath}); + let tx = await I_STRProxied.modifyTicker( + account_temp, + "LOG2", + "LOGAN2", + currentTime, + currentTime.add(new BN(duration.days(60))), + false, + { from: account_polymath } + ); await revertToSnapshot(snap_Id); - }) + }); }); describe("Test case for modifyTicker", async () => { it("Should add the custom ticker --failed because of bad owner", async () => { + currentTime = new BN(await latestTime()); await catchRevert( - I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), latestTime() + duration.days(10), false, { + I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", currentTime, currentTime.add(new BN(duration.days(10))), false, { from: account_temp }), "tx revert -> failed beacause of bad owner0" @@ -780,7 +773,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should add the custom ticker --fail ticker length should not be 0", async () => { await catchRevert( - I_STRProxied.modifyTicker(token_owner, "", "Ether", latestTime(), latestTime() + duration.days(10), false, { + I_STRProxied.modifyTicker(token_owner, "", "Ether", currentTime, currentTime.add(new BN(duration.days(10))), false, { from: account_polymath }), "tx revert -> failed beacause ticker length should not be 0" @@ -789,7 +782,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should add the custom ticker --failed because time should not be 0", async () => { await catchRevert( - I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", 0, latestTime() + duration.days(10), false, { + I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", new BN(0), currentTime.add(new BN(duration.days(10))), false, { from: account_polymath }), "tx revert -> failed because time should not be 0" @@ -797,8 +790,9 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the custom ticker --failed because registeration date is greater than the expiryDate", async () => { + let ctime = currentTime; await catchRevert( - I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), latestTime() - duration.minutes(10), false, { + I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", ctime, ctime.sub(new BN(duration.minutes(10))), false, { from: account_polymath }), "tx revert -> failed because registeration date is greater than the expiryDate" @@ -806,13 +800,14 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the custom ticker --failed because owner should not be 0x", async () => { + let ctime = currentTime; await catchRevert( I_STRProxied.modifyTicker( - "0x000000000000000000000000000000000000000000", + address_zero, "ETH", "Ether", - latestTime(), - latestTime() + duration.minutes(10), + ctime, + ctime.add(new BN(duration.minutes(10))), false, { from: account_polymath } ), @@ -821,12 +816,13 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should add the new custom ticker", async () => { + let ctime = currentTime; let tx = await I_STRProxied.modifyTicker( account_temp, "ETH", "Ether", - latestTime(), - latestTime() + duration.minutes(10), + ctime, + ctime.add(new BN(duration.minutes(10))), false, { from: account_polymath } ); @@ -835,12 +831,13 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should change the details of the existing ticker", async () => { + let ctime = currentTime; let tx = await I_STRProxied.modifyTicker( token_owner, "ETH", "Ether", - latestTime(), - latestTime() + duration.minutes(10), + ctime, + ctime.add(new BN(duration.minutes(10))), false, { from: account_polymath } ); @@ -859,7 +856,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should able to transfer the ticker ownership -- failed because new owner is 0x", async () => { await I_SecurityToken002.transferOwnership(account_temp, { from: token_owner }); await catchRevert( - I_STRProxied.transferTickerOwnership("0x00000000000000000000000000000000000000000", symbol2, { from: token_owner }), + I_STRProxied.transferTickerOwnership(address_zero, symbol2, { from: token_owner }), "tx revert -> failed because new owner is 0x" ); }); @@ -883,7 +880,7 @@ contract("SecurityTokenRegistry", accounts => { describe("Test case for the changeSecurityLaunchFee()", async () => { it("Should able to change the STLaunchFee-- failed because of bad owner", async () => { await catchRevert( - I_STRProxied.changeSecurityLaunchFee(web3.utils.toWei("500"), { from: account_temp }), + I_STRProxied.changeSecurityLaunchFee(new BN(web3.utils.toWei("500")), { from: account_temp }), "tx revert -> failed because of bad owner" ); }); @@ -896,10 +893,10 @@ 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 tx = await I_STRProxied.changeSecurityLaunchFee(new BN(web3.utils.toWei("500")), { from: account_polymath }); + assert.equal(tx.logs[0].args._newFee.toString(), new BN(web3.utils.toWei("500")).toString()); let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); - assert.equal(stLaunchFee, web3.utils.toWei("500")); + assert.equal(stLaunchFee.toString(), new BN(web3.utils.toWei("500")).toString()); }); }); @@ -929,7 +926,7 @@ contract("SecurityTokenRegistry", accounts => { describe("Test cases for the changeTickerRegistrationFee()", async () => { it("Should able to change the TickerRegFee-- failed because of bad owner", async () => { await catchRevert( - I_STRProxied.changeTickerRegistrationFee(web3.utils.toWei("500"), { from: account_temp }), + I_STRProxied.changeTickerRegistrationFee(new BN(web3.utils.toWei("500")), { from: account_temp }), "tx revert -> failed because of bad owner" ); }); @@ -942,10 +939,10 @@ 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 tx = await I_STRProxied.changeTickerRegistrationFee(new BN(web3.utils.toWei("400")), { from: account_polymath }); + assert.equal(tx.logs[0].args._newFee.toString(), new BN(web3.utils.toWei("400")).toString()); let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); - assert.equal(tickerRegFee, web3.utils.toWei("400")); + assert.equal(tickerRegFee.toString(), new BN(web3.utils.toWei("400")).toString()); }); it("Should fail to register the ticker with the old fee", async () => { @@ -957,8 +954,8 @@ contract("SecurityTokenRegistry", accounts => { }); 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 }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), token_owner); + await I_PolyToken.approve(I_STRProxied.address, new BN(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`); @@ -973,7 +970,7 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should launch the the securityToken", async () => { - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(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 @@ -1026,27 +1023,27 @@ contract("SecurityTokenRegistry", accounts => { 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 }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1000")), { from: account_temp }); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "0x0", { 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_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(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 }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1000")), { from: account_temp }); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "0x0", { 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_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(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 }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1000")), { from: account_temp }); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "0x0", { 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_Getter.getTickersByOwner.call(account_temp)).map(x => web3.utils.toUtf8(x))); @@ -1059,12 +1056,13 @@ contract("SecurityTokenRegistry", accounts => { }); it("Should modify ticker 1", async () => { + currentTime = new BN(await latestTime()); let tx = await I_STRProxied.modifyTicker( account_temp, "TOK1", "TOKEN 1", - latestTime(), - latestTime() + duration.minutes(10), + currentTime, + currentTime.add(new BN(duration.minutes(10))), false, { from: account_polymath } ); @@ -1079,8 +1077,8 @@ contract("SecurityTokenRegistry", accounts => { account_temp, "TOK3", "TOKEN 3", - latestTime(), - latestTime() + duration.minutes(10), + currentTime, + currentTime.add(new BN(duration.minutes(10))), false, { from: account_polymath } ); @@ -1092,18 +1090,13 @@ contract("SecurityTokenRegistry", accounts => { }); describe("Test cases for IRegistry functionality", async () => { describe("Test cases for reclaiming funds", async () => { - - it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { - I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); - await catchRevert( - I_STRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) - ); + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async () => { + I_PolyToken.transfer(I_STRProxied.address, new BN(web3.utils.toWei("1")), { from: token_owner }); + await catchRevert(I_STRProxied.reclaimERC20(address_zero, { from: account_polymath })); }); - it("Should successfully reclaim POLY tokens -- not authorised", async() => { - await catchRevert( - I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) - ); + it("Should successfully reclaim POLY tokens -- not authorised", async () => { + await catchRevert(I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp })); }); it("Should successfully reclaim POLY tokens", async () => { @@ -1111,8 +1104,8 @@ contract("SecurityTokenRegistry", accounts => { await I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_polymath }); 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() + bal2.div(new BN(10).pow(new BN(18))).toNumber(), + bal2.div(new BN(10).pow(new BN(18))).toNumber() ); }); }); @@ -1139,56 +1132,43 @@ contract("SecurityTokenRegistry", accounts => { }); }); - describe("Test cases for the setProtocolVersion", async() => { - - it("Should successfully change the protocolVersion -- failed because of bad owner", async() => { - await catchRevert( - I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp }) - ); + describe("Test cases for the setProtocolVersion", async () => { + it("Should successfully change the protocolVersion -- failed because of bad owner", async () => { + await catchRevert(I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp })); }); - - it("Should successfully change the protocolVersion -- failed because factory address is 0x", async() => { + + it("Should successfully change the protocolVersion -- failed because factory address is 0x", async () => { await catchRevert( - I_STRProxied.setProtocolVersion("0x000000000000000000000000000000000000000", 5, 6, 7, { from: account_polymath }) + I_STRProxied.setProtocolVersion(address_zero, 5, 6, 7, { from: account_polymath }) ); }); - - it("Should successfully change the protocolVersion -- not a valid vesrion", async() => { - await catchRevert( - I_STRProxied.setProtocolVersion(accounts[8], 0, 0, 0, { from: account_polymath }) - ); + + it("Should successfully change the protocolVersion -- not a valid vesrion", async () => { + await catchRevert(I_STRProxied.setProtocolVersion(accounts[8], new BN(0), new BN(0), new BN(0), { from: account_polymath })); }); - it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async() => { + it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async () => { let snap_Id = await takeSnapshot(); - await I_STRProxied.setProtocolVersion(accounts[8], 2, 3, 1, {from: account_polymath }); - await catchRevert( - I_STRProxied.setProtocolVersion(accounts[8], 1, 3, 1, {from: account_polymath }) - ); + await I_STRProxied.setProtocolVersion(accounts[8], 2, 3, 1, { from: account_polymath }); + await catchRevert(I_STRProxied.setProtocolVersion(accounts[8], 1, 3, 1, { from: account_polymath })); await revertToSnapshot(snap_Id); }); - }); - describe("Test cases for the transferOwnership", async() => { - - it("Should fail to transfer the ownership -- not authorised", async() => { - await catchRevert( - I_STRProxied.transferOwnership(account_temp, { from: account_issuer}) - ); + describe("Test cases for the transferOwnership", async () => { + it("Should fail to transfer the ownership -- not authorised", async () => { + await catchRevert(I_STRProxied.transferOwnership(account_temp, { from: account_issuer })); }); - it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { - await catchRevert( - I_STRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) - ); + it("Should fail to transfer the ownership -- 0x address is not allowed", async () => { + await catchRevert(I_STRProxied.transferOwnership(address_zero, { from: account_polymath })); }); - it("Should successfully transfer the ownership of the STR", async() => { + it("Should successfully transfer the ownership of the STR", async () => { let tx = await I_STRProxied.transferOwnership(account_temp, { from: account_polymath }); assert.equal(tx.logs[0].args.previousOwner, account_polymath); assert.equal(tx.logs[0].args.newOwner, account_temp); }); - }) + }); }); }); diff --git a/test/o_security_token.js b/test/o_security_token.js index 6ab78db67..aac62b9e0 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -9,7 +9,7 @@ import { deployCappedSTOAndVerifyed, deployMockRedemptionAndVerifyed, deployMockWrongTypeRedemptionAndVerifyed - } from "./helpers/createInstances"; +} from "./helpers/createInstances"; const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const CappedSTO = artifacts.require("./CappedSTO.sol"); @@ -19,10 +19,10 @@ const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager") const MockRedemptionManager = artifacts.require("./MockRedemptionManager.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("SecurityToken", accounts => { +contract("SecurityToken", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_investor1; @@ -36,7 +36,8 @@ contract("SecurityToken", accounts => { let account_delegate; let account_temp; let account_controller; - let address_zero = "0x0000000000000000000000000000000000000000"; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; let balanceOfReceiver; // investor Details @@ -83,25 +84,27 @@ contract("SecurityToken", accounts => { const budget = 0; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); // delagate details - const delegateDetails = "I am delegate .."; - const TM_Perm = "FLAGS"; - const TM_Perm_Whitelist = "WHITELIST"; + const delegateDetails = web3.utils.fromAscii("I am delegate .."); + const TM_Perm = web3.utils.fromAscii("FLAGS"); + const TM_Perm_Whitelist = web3.utils.fromAscii("WHITELIST"); // Capped STO details let startTime; let endTime; - const cap = web3.utils.toWei("10000"); - const rate = web3.utils.toWei("1000"); + const cap = new BN(web3.utils.toWei("10000")); + const rate = new BN(web3.utils.toWei("1000")); const fundRaiseType = [0]; - const cappedSTOSetupCost = web3.utils.toWei("20000", "ether"); + const cappedSTOSetupCost = new BN(web3.utils.toWei("20000", "ether")); const maxCost = cappedSTOSetupCost; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; + let currentTime; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; account_affiliate1 = accounts[2]; @@ -168,14 +171,14 @@ contract("SecurityToken", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not console.log(log.args); @@ -185,43 +188,43 @@ contract("SecurityToken", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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 fromTime = latestTime(); - let toTime = fromTime + duration.days(100); - let expiryTime = toTime + duration.days(100); + currentTime = new BN(await latestTime()); + let toTime = new BN(currentTime.add(new BN(duration.days(100)))); + let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, currentTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); assert.equal(tx.logs[0].args._investor, account_affiliate1, "Failed in adding the investor in whitelist"); - await catchRevert(I_SecurityToken.mint(account_investor1, 100 * Math.pow(10, 18), { from: account_delegate })); + await catchRevert(I_SecurityToken.mint(account_investor1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: account_delegate })); }); 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 }); + await I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner }); let balance = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); + assert.equal(balance.div(new BN(10).pow(new BN(18))).toNumber(), 100); }); it("Should mint the multi tokens before attaching the STO -- fail only be called by the owner", async () => { - let fromTime = latestTime(); - let toTime = fromTime + duration.days(100); - let expiryTime = toTime + duration.days(100); + currentTime = new BN(await latestTime()); + let toTime = new BN(currentTime.add(new BN(duration.days(100)))); + let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, fromTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, currentTime, toTime, expiryTime, true, { from: token_owner, gas: 6000000 }); assert.equal(tx.logs[0].args._investor, account_affiliate2, "Failed in adding the investor in whitelist"); await catchRevert( - I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [100 * Math.pow(10, 18), 110 * Math.pow(10, 18)], { + I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { from: account_delegate, gas: 500000 }) @@ -230,7 +233,7 @@ contract("SecurityToken", accounts => { it("Should mintMulti", async () => { await catchRevert( - I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [100 * Math.pow(10, 18)], { + I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18)))], { from: token_owner, gas: 500000 }) @@ -238,14 +241,13 @@ contract("SecurityToken", accounts => { }); 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 + await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { + from: token_owner }); let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); + assert.equal(balance1.div(new BN(10).pow(new BN(18))).toNumber(), 200); let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); - assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 110); + assert.equal(balance2.div(new BN(10).pow(new BN(18))).toNumber(), 110); }); it("Should finish the minting -- fail because feature is not activated", async () => { @@ -274,76 +276,77 @@ contract("SecurityToken", accounts => { let id = await takeSnapshot(); await I_SecurityToken.freezeMinting({ from: token_owner }); - await catchRevert(I_SecurityToken.mint(account_affiliate1, 100 * Math.pow(10, 18), { from: token_owner, gas: 500000 })); + await catchRevert(I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner, gas: 500000 })); await revertToSnapshot(id); }); it("Should fail to attach the STO factory because not enough poly in contract", async () => { - startTime = latestTime() + duration.seconds(5000); + startTime = await latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - await catchRevert(I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + await catchRevert(I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); it("Should fail to attach the STO factory because max cost too small", async () => { - startTime = latestTime() + duration.seconds(5000); + startTime = await 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 }); await catchRevert( - I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, web3.utils.toWei("1000", "ether"), 0, { from: token_owner }) + I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("1000", "ether")), new BN(0), { from: token_owner }) ); }); it("Should successfully add module with label", async () => { let snapId = await takeSnapshot(); - startTime = latestTime() + duration.seconds(5000); + startTime = await 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 }); console.log("0"); - const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, 'stofactory', { from: token_owner }); + const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), web3.utils.fromAscii("stofactory"), { + from: token_owner + }); console.log("1"); 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"); - console.log("module label is .. "+ web3.utils.toAscii(tx.logs[3].args._label)); + console.log("module label is .. " + web3.utils.toAscii(tx.logs[3].args._label)); assert(web3.utils.toAscii(tx.logs[3].args._label), "stofactory", "label doesnt match"); - I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); + I_CappedSTO = await CappedSTO.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); it("Should successfully attach the STO factory with the security token", async () => { - - startTime = latestTime() + duration.seconds(5000); + startTime = await 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 }); + const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(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); + I_CappedSTO = await 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 }); + await I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner }); let balance = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 300); + assert.equal(balance.div(new BN(10).pow(new BN(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 }); - await catchRevert(I_SecurityToken.mint(account_affiliate1, 100 * Math.pow(10, 18), { from: token_owner, gas: 500000 })); + await catchRevert(I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner })); await revertToSnapshot(id); }); }); @@ -366,7 +369,7 @@ contract("SecurityToken", accounts => { }); it("Should get the modules of the securityToken by name", async () => { - let moduleList = await I_SecurityToken.getModulesByName.call("CappedSTO"); + let moduleList = await I_SecurityToken.getModulesByName.call(web3.utils.fromAscii("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"); @@ -374,13 +377,13 @@ contract("SecurityToken", accounts => { }); 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"); + let moduleData = await I_SecurityToken.getModulesByName.call(web3.utils.fromAscii("GeneralPermissionManager")); + assert.isTrue(moduleData.length == new BN(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"); + let moduleData = await I_SecurityToken.getModulesByName.call(web3.utils.fromAscii("CountTransferManager")); + assert.isTrue(moduleData.length == new BN(0), "No Permission Manager"); }); it("Should fail in updating the token details", async () => { @@ -393,7 +396,7 @@ contract("SecurityToken", accounts => { }); it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async () => { - await catchRevert(I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from: token_owner })); + await catchRevert(I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from: account_delegate })); }); it("Should fail to remove the module - module not archived", async () => { @@ -401,7 +404,7 @@ contract("SecurityToken", accounts => { }); it("Should fail to remove the module - incorrect address", async () => { - await catchRevert(I_SecurityToken.removeModule(0, { from: token_owner })); + await catchRevert(I_SecurityToken.removeModule(address_zero, { from: token_owner })); }); it("Should successfully remove the general transfer manager module from the securityToken", async () => { @@ -410,13 +413,13 @@ contract("SecurityToken", accounts => { 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 I_SecurityToken.mint(account_investor1, web3.utils.toWei("500"), {from: token_owner}); - await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("200"), {from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); + await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("500")), { from: token_owner }); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("200")), { from: account_investor1 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).div(new BN(10).pow(new BN(18))).toNumber(), 200); await revertToSnapshot(key); }); - it("Should successfully remove the module from the middle of the names mapping", async() => { + it("Should successfully remove the module from the middle of the names mapping", async () => { let snap_Id = await takeSnapshot(); let D_GPM, D_GPM_1, D_GPM_2; let FactoryInstances; @@ -428,25 +431,23 @@ contract("SecurityToken", accounts => { FactoryInstances = [D_GPM, D_GPM_1, D_GPM_2]; // Adding module in the ST for (let i = 0; i < FactoryInstances.length; i++) { - let tx = await I_SecurityToken.addModule(FactoryInstances[i].address, "", 0, 0, {from: token_owner }); - assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "fail in adding the GPM") + let tx = await I_SecurityToken.addModule(FactoryInstances[i].address, "0x0", new BN(0), new BN(0), { from: token_owner }); + assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "fail in adding the GPM"); GPMAddress.push(tx.logs[2].args._module); } // Archive the one of the module - await I_SecurityToken.archiveModule(GPMAddress[0], {from: token_owner}); + await I_SecurityToken.archiveModule(GPMAddress[0], { from: token_owner }); // Remove the module - let tx = await I_SecurityToken.removeModule(GPMAddress[0], {from: token_owner}); + let tx = await I_SecurityToken.removeModule(GPMAddress[0], { from: token_owner }); assert.equal(tx.logs[0].args._types[0], permissionManagerKey); assert.equal(tx.logs[0].args._module, GPMAddress[0]); await revertToSnapshot(snap_Id); }); - it("Should successfully archive the module first and fail during achiving the module again", async() => { + it("Should successfully archive the module first and fail during achiving the module again", async () => { let key = await takeSnapshot(); await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from: token_owner }); - await catchRevert( - I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from: token_owner }) - ); + await catchRevert(I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from: token_owner })); await revertToSnapshot(key); }); @@ -469,9 +470,9 @@ contract("SecurityToken", accounts => { 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 I_SecurityToken.mint(one_address, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner, gas: 500000 }); + let balance = await I_SecurityToken.balanceOf(one_address); + assert.equal(balance.div(new BN(10).pow(new BN(18))).toNumber(), 100); await revertToSnapshot(key); }); @@ -487,48 +488,42 @@ contract("SecurityToken", accounts => { }); it("Should successfully unarchive the general transfer manager module from the securityToken -- fail because module is already unarchived", async () => { - await catchRevert( - I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from: token_owner }) - ); + await catchRevert(I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from: token_owner })); }); - it("Should successfully archive the module -- fail because module is not existed", async() => { - await catchRevert( - I_SecurityToken.archiveModule(I_GeneralPermissionManagerFactory.address, { from: token_owner }) - ); - }) + it("Should successfully archive the module -- fail because module is not existed", async () => { + await catchRevert(I_SecurityToken.archiveModule(I_GeneralPermissionManagerFactory.address, { from: token_owner })); + }); it("Should fail to mint tokens while GTM unarchived", async () => { - await catchRevert(I_SecurityToken.mint(1, 100 * Math.pow(10, 18), { from: token_owner, gas: 500000 })); + await catchRevert(I_SecurityToken.mint(one_address, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner, gas: 500000 })); }); it("Should change the budget of the module - fail incorrect address", async () => { - await catchRevert(I_SecurityToken.changeModuleBudget(0, 100 * Math.pow(10, 18), true, { from: token_owner })); + await catchRevert(I_SecurityToken.changeModuleBudget(address_zero, new BN(100).mul(new BN(10).pow(new BN(18))), true, { from: token_owner })); }); it("Should change the budget of the module", async () => { let budget = await I_PolyToken.allowance.call(I_SecurityToken.address, I_CappedSTO.address); - let increaseAmount = 100 * Math.pow(10, 18); + let increaseAmount = new BN(100).mul(new BN(10).pow(new BN(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.toNumber(), budget.plus(increaseAmount).toNumber()); + assert.equal(tx.logs[1].args._budget.toString(), budget.add(increaseAmount).toString()); }); - it("Should change the budget of the module (decrease it)", async() => { + it("Should change the budget of the module (decrease it)", async () => { let budget = await I_PolyToken.allowance.call(I_SecurityToken.address, I_CappedSTO.address); - let decreaseAmount = 100 * Math.pow(10, 18); + let decreaseAmount = new BN(100).mul(new BN(10).pow(new BN(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.toNumber(), budget.minus(decreaseAmount).toNumber()); + assert.equal(tx.logs[1].args._budget.toString(), budget.sub(decreaseAmount).toString()); }); - it("Should fail to get the total supply -- because checkpoint id is greater than present", async() => { - await catchRevert( - I_SecurityToken.totalSupplyAt.call(50) - ); - }) + it("Should fail to get the total supply -- because checkpoint id is greater than present", async () => { + await catchRevert(I_SecurityToken.totalSupplyAt.call(50)); + }); }); describe("General Transfer manager Related test cases", async () => { @@ -536,7 +531,7 @@ contract("SecurityToken", accounts => { balanceOfReceiver = await web3.eth.getBalance(account_fundsReceiver); // Add the Investor in to the whitelist - fromTime = latestTime(); + fromTime = await latestTime(); toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); @@ -553,25 +548,25 @@ contract("SecurityToken", accounts => { from: account_investor1, to: I_CappedSTO.address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(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.getRaised.call(0)).div(new BN(10).pow(new BN(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); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 1000); }); it("Should Fail in transferring the token from one whitelist investor 1 to non whitelist investor 2", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor2, 10 * Math.pow(10, 18), { from: account_investor1 })); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1 })); }); it("Should fail to provide the permission to the delegate to change the transfer bools -- Bad owner", async () => { // Add permission to the deletgate (A regesteration process) - await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); + await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; - I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); + I_GeneralPermissionManager = await GeneralPermissionManager.at(moduleData); await catchRevert(I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_temp })); }); @@ -593,7 +588,7 @@ contract("SecurityToken", accounts => { }); it("Should fail to send tokens with the wrong granularity", async () => { - await catchRevert(I_SecurityToken.transfer(accounts[7], Math.pow(10, 17), { from: account_investor1 })); + await catchRevert(I_SecurityToken.transfer(accounts[7], new BN(10).pow(new BN(17)), { from: account_investor1 })); }); it("Should adjust granularity", async () => { @@ -601,24 +596,24 @@ contract("SecurityToken", accounts => { }); it("Should adjust granularity", async () => { - 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 }); + await I_SecurityToken.changeGranularity(new BN(10).pow(new BN(17)), { from: token_owner }); + await I_SecurityToken.transfer(accounts[7], new BN(10).pow(new BN(17)), { from: account_investor1, gas: 2500000 }); + await I_SecurityToken.transfer(account_investor1, new BN(10).pow(new BN(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 }); + await I_SecurityToken.transfer(accounts[7], new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1, gas: 2500000 }); assert.equal( - (await I_SecurityToken.balanceOf(accounts[7])).dividedBy(new BigNumber(10).pow(18)).toNumber(), + (await I_SecurityToken.balanceOf(accounts[7])).div(new BN(10).pow(new BN(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 }); + await I_SecurityToken.transfer(account_temp, new BN(5).mul(new BN(10).pow(new BN(18))), { from: accounts[7], gas: 2500000 }); assert.equal( - (await I_SecurityToken.balanceOf(account_temp)).dividedBy(new BigNumber(10).pow(18)).toNumber(), + (await I_SecurityToken.balanceOf(account_temp)).div(new BN(10).pow(new BN(18))).toNumber(), 5, "Transfer doesn't take place properly" ); @@ -644,53 +639,52 @@ contract("SecurityToken", accounts => { 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 }); + await I_SecurityToken.transfer(account_investor2, new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1, gas: 2500000 }); assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), + (await I_SecurityToken.balanceOf(account_investor2)).div(new BN(10).pow(new BN(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 }); + let tx = await I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.approve(account_investor1, new BN(2).mul(new BN(10).pow(new BN(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), { + let log = await I_SecurityToken.transferFrom(account_investor2, account_investor3, new BN(2).mul(new BN(10).pow(new BN(18))), { from: account_investor1 }); - assert.equal(log.logs[0].args.value.toNumber(), 2 * Math.pow(10, 18)); + assert.equal(log.logs[0].args.value.toString(), new BN(2).mul(new BN(10).pow(new BN(18))).toString()); }); it("Should Fail in trasferring from whitelist investor1 to non-whitelist investor", async () => { - await catchRevert(I_SecurityToken.transfer(account_temp, 10 * Math.pow(10, 18), { from: account_investor1, gas: 2500000 })); + await catchRevert(I_SecurityToken.transfer(account_temp, new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1, gas: 2500000 })); 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 }); + await I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner }); let balance = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance.dividedBy(new BigNumber(10).pow(18)).toNumber(), 400); + assert.equal(balance.div(new BN(10).pow(new BN(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 + await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { + from: token_owner }); let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); - assert.equal(balance1.dividedBy(new BigNumber(10).pow(18)).toNumber(), 500); + assert.equal(balance1.div(new BN(10).pow(new BN(18))).toNumber(), 500); let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); - assert.equal(balance2.dividedBy(new BigNumber(10).pow(18)).toNumber(), 220); + assert.equal(balance2.div(new BN(10).pow(new BN(18))).toNumber(), 220); }); it("Should provide more permissions to the delegate", async () => { @@ -719,14 +713,14 @@ contract("SecurityToken", accounts => { from: account_temp, to: I_CappedSTO.address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(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.getRaised.call(0)).div(new BN(10).pow(new BN(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); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 1000); }); it("STO should fail to mint tokens after minting is frozen", async () => { @@ -738,14 +732,14 @@ contract("SecurityToken", accounts => { from: account_temp, to: I_CappedSTO.address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(web3.utils.toWei("1", "ether")) }) ); 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, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, new BN(0), new BN(0), new BN(0), true, { from: account_delegate, gas: 6000000 }); @@ -759,7 +753,7 @@ contract("SecurityToken", accounts => { from: account_temp, to: I_CappedSTO.address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(web3.utils.toWei("1", "ether")) }) ); }); @@ -786,7 +780,7 @@ contract("SecurityToken", accounts => { from: account_temp, to: I_CappedSTO.address, gas: 2100000, - value: web3.utils.toWei("1", "ether") + value: new BN(web3.utils.toWei("1", "ether")) }) ); }); @@ -795,7 +789,7 @@ contract("SecurityToken", accounts => { await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, { from: token_owner }); console.log(await I_SecurityToken.balanceOf(account_investor1)); - await catchRevert(I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), { from: account_temp })); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_temp })); }); it("Should unfreeze all the transfers", async () => { @@ -808,7 +802,7 @@ contract("SecurityToken", accounts => { }); 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_temp }); }); it("Should check that the list of investors is correct", async () => { @@ -856,7 +850,7 @@ contract("SecurityToken", accounts => { let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); await catchRevert( - I_SecurityToken.forceBurn(account_temp, currentBalance + web3.utils.toWei("500", "ether"), "", "", { + I_SecurityToken.forceBurn(account_temp, currentBalance + new BN(web3.utils.toWei("500", "ether")), "0x0", "0x0", { from: account_controller }) ); @@ -865,16 +859,16 @@ contract("SecurityToken", accounts => { await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, { from: token_owner }); let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); - await catchRevert(I_SecurityToken.forceBurn(account_temp, currentBalance, "", "", { from: token_owner })); + await catchRevert(I_SecurityToken.forceBurn(account_temp, currentBalance, "0x0", "0x0", { from: token_owner })); }); 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 }); + let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "0x0", "0x0", { from: account_controller }); // console.log(tx.logs[1].args._value.toNumber(), currentBalance.toNumber()); - assert.equal(tx.logs[1].args._value.toNumber(), currentBalance.toNumber()); + assert.equal(tx.logs[1].args._value.toString(), currentBalance.toString()); let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); // console.log(newInvestorCount.toString()); assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); @@ -894,8 +888,8 @@ contract("SecurityToken", accounts => { 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.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); @@ -911,8 +905,8 @@ contract("SecurityToken", accounts => { 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}); + 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 () => { @@ -934,9 +928,7 @@ contract("SecurityToken", accounts => { assert.equal(filteredInvestors[2], investors[2]); assert.equal(filteredInvestors[3], investors[3]); assert.equal(filteredInvestors.length, 4); - await catchRevert( - I_SecurityToken.iterateInvestors(0, 5) - ); + await catchRevert(I_SecurityToken.iterateInvestors(0, 5)); }); it("Should check the balance of investor at checkpoint", async () => { @@ -949,112 +941,116 @@ contract("SecurityToken", accounts => { }); }); - describe("Test cases for the Mock TrackedRedeemption", async() => { - - it("Should add the tracked redeemption module successfully", async() => { + 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, 0); - let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); + let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); assert.equal(tx.logs[2].args._types[0], burnKey, "fail in adding the burn manager"); - I_MockRedemptionManager = MockRedemptionManager.at(tx.logs[2].args._module); + I_MockRedemptionManager = await MockRedemptionManager.at(tx.logs[2].args._module); // adding the burn module into the GTM + currentTime = new BN(await latestTime()); tx = await I_GeneralTransferManager.modifyWhitelist( I_MockRedemptionManager.address, - latestTime(), - latestTime() + duration.seconds(2), - latestTime() + duration.days(50), + currentTime, + currentTime.add(new BN(duration.seconds(2))), + currentTime.add(new BN(duration.days(50))), true, { - from: account_delegate, - gas: 6000000 + from: account_delegate, + gas: 6000000 } ); assert.equal(tx.logs[0].args._investor, I_MockRedemptionManager.address, "Failed in adding the investor in whitelist"); }); - it("Should successfully burn tokens", async() => { - await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(false, {from: token_owner}); + it("Should successfully burn tokens", async () => { + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(false, { from: token_owner }); // Minting some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei("1000"), {from: token_owner}); + await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1000")), { from: token_owner }); // Provide approval to trnafer the tokens to Module - await I_SecurityToken.approve(I_MockRedemptionManager.address, web3.utils.toWei("500"), {from: account_investor1}); + await I_SecurityToken.approve(I_MockRedemptionManager.address, new BN(web3.utils.toWei("500")), { from: account_investor1 }); // Allow all whitelist transfer - await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from: token_owner}); + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, { from: token_owner }); // Transfer the tokens to module (Burn) - await I_MockRedemptionManager.transferToRedeem(web3.utils.toWei("500"), { from: account_investor1}); + await I_MockRedemptionManager.transferToRedeem(new BN(web3.utils.toWei("500")), { from: account_investor1 }); // Redeem tokens - let tx = await I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}); + let tx = await I_MockRedemptionManager.redeemTokenByOwner(new BN(web3.utils.toWei("250")), { from: account_investor1 }); assert.equal(tx.logs[0].args._investor, account_investor1, "Burn tokens of wrong owner"); - assert.equal((tx.logs[0].args._value).dividedBy(new BigNumber(10).pow(18)).toNumber(), 250); + assert.equal(tx.logs[0].args._value.div(new BN(10).pow(new BN(18))).toNumber(), 250); }); - it("Should fail to burn the tokens because module get archived", async() => { - await I_SecurityToken.archiveModule(I_MockRedemptionManager.address, {from: token_owner}); - await catchRevert( - I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}) - ); - }) + it("Should fail to burn the tokens because module get archived", async () => { + await I_SecurityToken.archiveModule(I_MockRedemptionManager.address, { from: token_owner }); + await catchRevert(I_MockRedemptionManager.redeemTokenByOwner(new BN(web3.utils.toWei("250")), { from: account_investor1 })); + }); - it("Should successfully fail in calling the burn functions", async() => { + it("Should successfully fail in calling the burn functions", async () => { [I_MockRedemptionManagerFactory] = await deployMockWrongTypeRedemptionAndVerifyed(account_polymath, I_MRProxied, 0); - let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); - I_MockRedemptionManager = MockRedemptionManager.at(tx.logs[2].args._module); + let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); + I_MockRedemptionManager = await MockRedemptionManager.at(tx.logs[2].args._module); - // adding the burn module into the GTM - tx = await I_GeneralTransferManager.modifyWhitelist( + // adding the burn module into the GTM + currentTime = new BN(await latestTime()); + tx = await I_GeneralTransferManager.modifyWhitelist( I_MockRedemptionManager.address, - latestTime(), - latestTime() + duration.seconds(2), - latestTime() + duration.days(50), + currentTime, + currentTime.add(new BN(duration.seconds(2))), + currentTime.add(new BN(duration.days(50))), true, { - from: account_delegate, - gas: 6000000 + from: account_delegate, + gas: 6000000 } ); assert.equal(tx.logs[0].args._investor, I_MockRedemptionManager.address, "Failed in adding the investor in whitelist"); // Provide approval to trnafer the tokens to Module - await I_SecurityToken.approve(I_MockRedemptionManager.address, web3.utils.toWei("500"), {from: account_investor1}); + await I_SecurityToken.approve(I_MockRedemptionManager.address, new BN(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 I_MockRedemptionManager.transferToRedeem(new BN(web3.utils.toWei("500")), { from: account_investor1 }); await catchRevert( // Redeem tokens - I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}) + I_MockRedemptionManager.redeemTokenByOwner(new BN(web3.utils.toWei("250")), { from: account_investor1 }) ); }); - - }) + }); describe("Withdraw Poly", async () => { - it("Should successfully withdraw the poly -- failed because of zero address of token", async() => { - await catchRevert(I_SecurityToken.withdrawERC20("0x00000000000000000000000000000000000000000", web3.utils.toWei("20000", "ether"), { from: account_temp })); - }) + it("Should successfully withdraw the poly -- failed because of zero address of token", async () => { + await catchRevert( + I_SecurityToken.withdrawERC20(address_zero, new BN(web3.utils.toWei("20000", "ether")), { + from: account_temp + }) + ); + }); it("Should successfully withdraw the poly", async () => { - await catchRevert(I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("20000", "ether"), { from: account_temp })); + await catchRevert( + I_SecurityToken.withdrawERC20(I_PolyToken.address, new BN(web3.utils.toWei("20000", "ether")), { from: account_temp }) + ); }); it("Should successfully withdraw the poly", async () => { let balanceBefore = await I_PolyToken.balanceOf(token_owner); - await I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("20000", "ether"), { from: token_owner }); + await I_SecurityToken.withdrawERC20(I_PolyToken.address, new BN(web3.utils.toWei("20000", "ether")), { from: token_owner }); let balanceAfter = await I_PolyToken.balanceOf(token_owner); assert.equal( - BigNumber(balanceAfter) - .sub(new BigNumber(balanceBefore)) - .toNumber(), - web3.utils.toWei("20000", "ether") + BN(balanceAfter) + .sub(new BN(balanceBefore)) + .toString(), + new BN(web3.utils.toWei("20000", "ether").toString()) ); }); it("Should successfully withdraw the poly", async () => { - await catchRevert(I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("10", "ether"), { from: token_owner })); + await catchRevert(I_SecurityToken.withdrawERC20(I_PolyToken.address, new BN(web3.utils.toWei("10", "ether")), { from: token_owner })); }); }); describe("Force Transfer", async () => { it("Should fail to forceTransfer because not approved controller", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", { + I_SecurityToken.forceTransfer(account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_investor1 }) ); @@ -1062,7 +1058,7 @@ contract("SecurityToken", accounts => { it("Should fail to forceTransfer because insufficient balance", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor2, account_investor1, web3.utils.toWei("10", "ether"), "", "reason", { + I_SecurityToken.forceTransfer(account_investor2, account_investor1, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_controller }) ); @@ -1070,7 +1066,7 @@ contract("SecurityToken", accounts => { it("Should fail to forceTransfer because recipient is zero address", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor1, address_zero, web3.utils.toWei("10", "ether"), "", "reason", { + I_SecurityToken.forceTransfer(account_investor1, address_zero, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_controller }) ); @@ -1087,9 +1083,9 @@ contract("SecurityToken", accounts => { let tx = await I_SecurityToken.forceTransfer( account_investor1, account_investor2, - web3.utils.toWei("10", "ether"), - "", - "reason", + new BN(web3.utils.toWei("10", "ether")), + "0x0", + web3.utils.fromAscii("reason"), { from: account_controller } ); @@ -1097,15 +1093,15 @@ contract("SecurityToken", accounts => { 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_investorCount.add(new BN(1)).toNumber(), end_investorCount.toNumber(), "Investor count not changed"); assert.equal( - start_balInv1.sub(web3.utils.toWei("10", "ether")).toNumber(), - end_balInv1.toNumber(), + start_balInv1.sub(new BN(web3.utils.toWei("10", "ether"))).toString(), + end_balInv1.toString(), "Investor balance not changed" ); assert.equal( - start_balInv2.add(web3.utils.toWei("10", "ether")).toNumber(), - end_balInv2.toNumber(), + start_balInv2.add(new BN(web3.utils.toWei("10", "ether"))).toString(), + end_balInv2.toString(), "Investor balance not changed" ); let eventForceTransfer = tx.logs[1]; @@ -1115,14 +1111,14 @@ contract("SecurityToken", accounts => { assert.equal(account_controller, eventForceTransfer.args._controller, "Event not emitted as expected"); assert.equal(account_investor1, eventForceTransfer.args._from, "Event not emitted as expected"); assert.equal(account_investor2, eventForceTransfer.args._to, "Event not emitted as expected"); - assert.equal(web3.utils.toWei("10", "ether"), eventForceTransfer.args._value, "Event not emitted as expected"); + assert.equal(new BN(web3.utils.toWei("10", "ether")).toString(), eventForceTransfer.args._value.toString(), "Event not emitted as expected"); console.log(eventForceTransfer.args._verifyTransfer); assert.equal(false, eventForceTransfer.args._verifyTransfer, "Event not emitted as expected"); assert.equal("reason", web3.utils.hexToUtf8(eventForceTransfer.args._data), "Event not emitted as expected"); assert.equal(account_investor1, eventTransfer.args.from, "Event not emitted as expected"); assert.equal(account_investor2, eventTransfer.args.to, "Event not emitted as expected"); - assert.equal(web3.utils.toWei("10", "ether"), eventTransfer.args.value, "Event not emitted as expected"); + assert.equal(new BN(web3.utils.toWei("10", "ether")).toString(), eventTransfer.args.value.toString(), "Event not emitted as expected"); }); it("Should fail to freeze controller functionality because not owner", async () => { @@ -1157,11 +1153,10 @@ contract("SecurityToken", accounts => { it("Should fail to forceTransfer because controller functionality frozen", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "", "reason", { + I_SecurityToken.forceTransfer(account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_controller }) ); }); }); - }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 3bf09d604..1ee447b7f 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -12,10 +12,12 @@ const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("USDTieredSTO", accounts => { +contract("USDTieredSTO", async (accounts) => { + let e18; + let e16; // Accounts Variable declaration let POLYMATH; let ISSUER; @@ -72,14 +74,15 @@ contract("USDTieredSTO", accounts => { const STOKEY = 3; let snapId; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // Initial fee for ticker registry and security token registry - const REGFEE = web3.utils.toWei("250"); + let REGFEE; const STOSetupCost = 0; // MockOracle USD prices - const USDETH = new BigNumber(500).mul(10 ** 18); // 500 USD/ETH - const USDPOLY = new BigNumber(25).mul(10 ** 16); // 0.25 USD/POLY + let USDETH; // 500 USD/ETH + let USDPOLY; // 0.25 USD/POLY // STO Configuration Arrays let _startTime = []; @@ -166,13 +169,14 @@ contract("USDTieredSTO", accounts => { async function convert(_stoID, _tier, _discount, _currencyFrom, _currencyTo, _amount) { let USDTOKEN; - if (_discount) USDTOKEN = ((await I_USDTieredSTO_Array[_stoID].tiers.call(_tier))[1]); - else USDTOKEN = ((await I_USDTieredSTO_Array[_stoID].tiers.call(_tier))[0]); + _amount = new BN(_amount); + if (_discount) USDTOKEN = (await I_USDTieredSTO_Array[_stoID].tiers.call(_tier))[1]; + else USDTOKEN = (await I_USDTieredSTO_Array[_stoID].tiers.call(_tier))[0]; + USDTOKEN = new BN(USDTOKEN); if (_currencyFrom == "TOKEN") { - let tokenToUSD = _amount - .div(10 ** 18) - .mul(USDTOKEN.div(10 ** 18)) - .mul(10 ** 18); // TOKEN * USD/TOKEN = USD + let tokenToUSD = new BN(_amount) + .mul(USDTOKEN) + .div(e18); if (_currencyTo == "USD") return tokenToUSD; if (_currencyTo == "ETH") { return await I_USDTieredSTO_Array[_stoID].convertFromUSD(ETH, tokenToUSD); @@ -181,20 +185,27 @@ contract("USDTieredSTO", accounts => { } } if (_currencyFrom == "USD") { - if (_currencyTo == "TOKEN") return _amount.div(USDTOKEN).mul(10 ** 18); // USD / USD/TOKEN = TOKEN + if (_currencyTo == "TOKEN") return _amount.div(USDTOKEN).mul(e18); // 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 + if (_currencyTo == "TOKEN") return ethToUSD.div(USDTOKEN).mul(e18); // USD / USD/TOKEN = TOKEN } return 0; } + let currentTime; + before(async () => { - // Accounts setup + e18 = new BN(10).pow(new BN(18)); + e16 = new BN(10).pow(new BN(16)); + currentTime = new BN(await latestTime()); + REGFEE = new BN(web3.utils.toWei("250")); + USDETH = new BN(500).mul(new BN(10).pow(new BN(18))); // 500 USD/ETH + USDPOLY = new BN(25).mul(new BN(10).pow(new BN(16))); // 0.25 USD/POLY POLYMATH = accounts[0]; ISSUER = accounts[1]; WALLET = accounts[2]; @@ -231,10 +242,10 @@ contract("USDTieredSTO", accounts => { // STEP 5: Deploy the USDTieredSTOFactory [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, STOSetupCost); - [P_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, web3.utils.toWei("500")); + [P_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, new BN(web3.utils.toWei("500"))); // 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 + I_USDOracle = await MockOracle.new(address_zero, web3.utils.fromAscii("ETH"), web3.utils.fromAscii("USD"), USDETH, { from: POLYMATH }); // 500 dollars per POLY + I_POLYOracle = await MockOracle.new(I_PolyToken.address, web3.utils.fromAscii("POLY"), web3.utils.fromAscii("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 }); @@ -269,22 +280,22 @@ contract("USDTieredSTO", accounts => { 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[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), TMKEY); + assert.equal(log.args._types[0].toString(), 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); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -292,14 +303,14 @@ contract("USDTieredSTO", accounts => { 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(new BigNumber(10 ** 18)), BigNumber(200000000).mul(new BigNumber(10 ** 18))]); // [ 100m Token, 200m Token ] - _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0)]); // [ 0, 0 ] - _nonAccreditedLimitUSD.push(new BigNumber(10000).mul(new BigNumber(10 ** 18))); // 10k USD - _minimumInvestmentUSD.push(new BigNumber(5 * 10 ** 18)); // 5 USD + _startTime.push(new BN(currentTime).add(new BN(duration.days(2)))); + _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(duration.days(100))))); + _ratePerTier.push([new BN(10).mul(e16), new BN(15).mul(e16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] + _ratePerTierDiscountPoly.push([new BN(10).mul(e16), new BN(15).mul(e16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] + _tokensPerTierTotal.push([new BN(100000000).mul(new BN(e18)), new BN(200000000).mul(new BN(e18))]); // [ 100m Token, 200m Token ] + _tokensPerTierDiscountPoly.push([new BN(0), new BN(0)]); // [ new BN(0), 0 ] + _nonAccreditedLimitUSD.push(new BN(10000).mul(new BN(e18))); // 10k USD + _minimumInvestmentUSD.push(new BN(5).mul(e18)); // 5 USD _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); @@ -321,44 +332,44 @@ contract("USDTieredSTO", accounts => { ]; 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 }); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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)); + I_USDTieredSTO_Array.push(await 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"); + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()).toString(), _startTime[stoId].toString(), "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()).toString(), _endTime[stoId].toString(), "Incorrect _endTime 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(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[0].toString(), + _ratePerTier[stoId][i].toString(), "Incorrect _ratePerTier in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toNumber(), - _ratePerTierDiscountPoly[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toString(), + _ratePerTierDiscountPoly[stoId][i].toString(), "Incorrect _ratePerTierDiscountPoly in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toNumber(), - _tokensPerTierTotal[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toString(), + _tokensPerTierTotal[stoId][i].toString(), "Incorrect _tokensPerTierTotal in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), - _tokensPerTierDiscountPoly[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toString(), + _tokensPerTierDiscountPoly[stoId][i].toString(), "Incorrect _tokensPerTierDiscountPoly in config" ); } assert.equal( - (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), - _nonAccreditedLimitUSD[stoId].toNumber(), + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toString(), + _nonAccreditedLimitUSD[stoId].toString(), "Incorrect _nonAccreditedLimitUSD in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), - _minimumInvestmentUSD[stoId].toNumber(), + (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toString(), + _minimumInvestmentUSD[stoId].toString(), "Incorrect _minimumInvestmentUSD in config" ); assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(), _wallet[stoId], "Incorrect _wallet in config"); @@ -373,10 +384,10 @@ contract("USDTieredSTO", accounts => { _tokensPerTierTotal[stoId].length, "Incorrect number of tiers" ); - assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); + assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, new BN(0), "Incorrect number of permissions"); }); - it("Should attach the paid STO factory -- failed because of no tokens", async() => { + it("Should attach the paid STO factory -- failed because of no tokens", async () => { let stoId = 0; // No discount let config = [ _startTime[stoId], @@ -395,11 +406,14 @@ contract("USDTieredSTO", accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); await catchRevert( - I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }) + I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + from: ISSUER, + gasPrice: GAS_PRICE + }) ); }); - it("Should attach the paid STO factory", async() => { + it("Should attach the paid STO factory", async () => { let snapId = await takeSnapshot(); let stoId = 0; // No discount let config = [ @@ -418,8 +432,11 @@ contract("USDTieredSTO", accounts => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); - let tx = await I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + let tx = await I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + from: ISSUER, + gasPrice: GAS_PRICE + }); await revertToSnapshot(snapId); }); @@ -431,60 +448,58 @@ contract("USDTieredSTO", accounts => { }); it("Should allow non-matching beneficiary -- failed because it is already active", async () => { - await catchRevert( - I_USDTieredSTO_Array[0].changeAllowBeneficialInvestments(true, { from: ISSUER }) - ); + await catchRevert(I_USDTieredSTO_Array[0].changeAllowBeneficialInvestments(true, { from: ISSUER })); await revertToSnapshot(snapId); }); - it("Should successfully call the modifyTimes before starting the STO -- fail because of bad owner", async() => { + it("Should successfully call the modifyTimes before starting the STO -- fail because of bad owner", async () => { await catchRevert( - I_USDTieredSTO_Array[0].modifyTimes(latestTime() + duration.days(15), latestTime() + duration.days(55), { from: POLYMATH }) + I_USDTieredSTO_Array[0].modifyTimes(new BN(currentTime).add(new BN(duration.days(15))), new BN(currentTime).add(new BN(duration.days(55))), { from: POLYMATH }) ); - }) + }); - it("Should successfully call the modifyTimes before starting the STO", async() => { + it("Should successfully call the modifyTimes before starting the STO", async () => { let snapId = await takeSnapshot(); - let _startTime = latestTime() + duration.days(15); - let _endTime = latestTime() + duration.days(55) + let _startTime = new BN(currentTime).add(new BN(duration.days(15))); + let _endTime = new BN(currentTime).add(new BN(duration.days(55))); await I_USDTieredSTO_Array[0].modifyTimes(_startTime, _endTime, { from: ISSUER }); - assert.equal(await I_USDTieredSTO_Array[0].startTime.call(), _startTime, "Incorrect _startTime in config"); - assert.equal(await I_USDTieredSTO_Array[0].endTime.call(), _endTime, "Incorrect _endTime in config"); + assert.equal((await I_USDTieredSTO_Array[0].startTime.call()).toString(), _startTime.toString(), "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[0].endTime.call()).toString(), _endTime.toString(), "Incorrect _endTime in config"); await revertToSnapshot(snapId); }); 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)); + _startTime.push(new BN(currentTime).add(new BN(duration.days(2)))); + _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(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) + new BN(10).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16) ]); _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) + new BN(10).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16), + new BN(15).mul(e16) ]); _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) + new BN(5).mul(e18), + new BN(10).mul(e18), + new BN(10).mul(e18), + new BN(10).mul(e18), + new BN(10).mul(e18), + new BN(50).mul(e18) ]); - _tokensPerTierDiscountPoly.push([BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0), BigNumber(0)]); - _nonAccreditedLimitUSD.push(new BigNumber(10000).mul(new BigNumber(10 ** 18))); - _minimumInvestmentUSD.push(new BigNumber(0)); + _tokensPerTierDiscountPoly.push([new BN(0), new BN(0), new BN(0), new BN(0), new BN(0), new BN(0)]); + _nonAccreditedLimitUSD.push(new BN(10000).mul(new BN(e18))); + _minimumInvestmentUSD.push(new BN(0)); _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); @@ -506,44 +521,44 @@ contract("USDTieredSTO", accounts => { ]; 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 }); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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)); + I_USDTieredSTO_Array.push(await 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"); + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()).toString(), _startTime[stoId].toString(), "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()).toString(), _endTime[stoId].toString(), "Incorrect _endTime 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(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[0].toString(), + _ratePerTier[stoId][i].toString(), "Incorrect _ratePerTier in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toNumber(), - _ratePerTierDiscountPoly[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toString(), + _ratePerTierDiscountPoly[stoId][i].toString(), "Incorrect _ratePerTierDiscountPoly in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toNumber(), - _tokensPerTierTotal[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toString(), + _tokensPerTierTotal[stoId][i].toString(), "Incorrect _tokensPerTierTotal in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), - _tokensPerTierDiscountPoly[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toString(), + _tokensPerTierDiscountPoly[stoId][i].toString(), "Incorrect _tokensPerTierDiscountPoly in config" ); } assert.equal( - (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), - _nonAccreditedLimitUSD[stoId].toNumber(), + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toString(), + _nonAccreditedLimitUSD[stoId].toString(), "Incorrect _nonAccreditedLimitUSD in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), - _minimumInvestmentUSD[stoId].toNumber(), + (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toString(), + _minimumInvestmentUSD[stoId].toString(), "Incorrect _minimumInvestmentUSD in config" ); assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(), _wallet[stoId], "Incorrect _wallet in config"); @@ -558,25 +573,23 @@ contract("USDTieredSTO", accounts => { _tokensPerTierTotal[stoId].length, "Incorrect number of tiers" ); - assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); + assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, new BN(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(new BigNumber(25 * 10 ** 18)); // [ 25 USD ] - _minimumInvestmentUSD.push(new BigNumber(5)); + _startTime.push(new BN(currentTime).add(new BN(duration.days(2)))); + _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(duration.days(100))))); + _ratePerTier.push([new BN(1).mul(e18), new BN(150).mul(e16)]); // [ 1 USD/Token, 1.5 USD/Token ] + _ratePerTierDiscountPoly.push([new BN(50).mul(e16), new BN(1).mul(e18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] + _tokensPerTierTotal.push([new BN(100).mul(e18), new BN(50).mul(e18)]); // [ 100 Token, 50 Token ] + _tokensPerTierDiscountPoly.push([new BN(100).mul(e18), new BN(25).mul(e18)]); // [ 100 Token, 25 Token ] + _nonAccreditedLimitUSD.push(new BN(25).mul(e18)); // [ 25 USD ] + _minimumInvestmentUSD.push(new BN(5)); _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); _usdToken.push(I_DaiToken.address); - let config = [ _startTime[stoId], _endTime[stoId], @@ -591,26 +604,25 @@ contract("USDTieredSTO", accounts => { _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 }); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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)); + I_USDTieredSTO_Array.push(await 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(new BigNumber(10000).mul(new BigNumber(10 ** 18))); - _minimumInvestmentUSD.push(new BigNumber(0)); + _startTime.push(new BN(currentTime).add(new BN(duration.days(0.1)))); + _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(duration.days(0.1))))); + _ratePerTier.push([new BN(10).mul(e16), new BN(15).mul(e16)]); + _ratePerTierDiscountPoly.push([new BN(10).mul(e16), new BN(12).mul(e16)]); + _tokensPerTierTotal.push([new BN(100).mul(e18), new BN(200).mul( e18)]); + _tokensPerTierDiscountPoly.push([new BN(0), new BN(50).mul( e18)]); + _nonAccreditedLimitUSD.push(new BN(10000).mul(new BN(e18))); + _minimumInvestmentUSD.push(new BN(0)); _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); @@ -632,24 +644,24 @@ contract("USDTieredSTO", accounts => { ]; 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 }); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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)); + I_USDTieredSTO_Array.push(await 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)); + _startTime.push(new BN(currentTime).add(new BN(duration.days(2)))); + _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(duration.days(100))))); + _ratePerTier.push([new BN(1).mul(e18), new BN(150).mul(e16)]); // [ 1 USD/Token, 1.5 USD/Token ] + _ratePerTierDiscountPoly.push([new BN(50).mul(e16), new BN(1).mul(e18)]); // [ 0.5 USD/Token, 1.5 USD/Token ] + _tokensPerTierTotal.push([new BN(100).mul(e18), new BN(50).mul( e18)]); // [ 100 Token, 50 Token ] + _tokensPerTierDiscountPoly.push([new BN(100).mul(e18), new BN(25).mul(e18)]); // [ 100 Token, 25 Token ] + _nonAccreditedLimitUSD.push(new BN(25).mul(e18)); // [ 25 USD ] + _minimumInvestmentUSD.push(new BN(5)); _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); @@ -671,11 +683,11 @@ contract("USDTieredSTO", accounts => { ]; 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 }); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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)); + I_USDTieredSTO_Array.push(await USDTieredSTO.at(tx.logs[2].args._module)); }); it("Should fail because rates and tier array of different length", async () => { @@ -746,14 +758,14 @@ contract("USDTieredSTO", accounts => { for (var i = 0; i < config.length; i++) { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config[i]); - await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER })); + await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER })); } }); 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 ratePerTier = [new BN(10).mul(e16), new BN(0)]; let config = [ _startTime[stoId], _endTime[stoId], @@ -770,7 +782,7 @@ contract("USDTieredSTO", accounts => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER })); + await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER })); }); it("Should fail because Zero address is not permitted for wallet", async () => { @@ -793,7 +805,7 @@ contract("USDTieredSTO", accounts => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER })); + await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER })); }); it("Should fail because Zero address is not permitted for reserveWallet", async () => { @@ -815,14 +827,14 @@ contract("USDTieredSTO", accounts => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER })); + await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER })); }); 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 startTime = await latestTime() + duration.days(35); + let endTime = await latestTime() + duration.days(1); let config = [ startTime, endTime, @@ -839,13 +851,13 @@ contract("USDTieredSTO", accounts => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER })); + await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER })); }); it("Should fail because start time is in the past", async () => { let stoId = 0; - let startTime = latestTime() - duration.days(35); + let startTime = await latestTime() - duration.days(35); let endTime = startTime + duration.days(50); let config = [ startTime, @@ -863,7 +875,7 @@ contract("USDTieredSTO", accounts => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER })); + await catchRevert(I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER })); }); }); @@ -886,52 +898,52 @@ contract("USDTieredSTO", accounts => { it("Should successfully change config before startTime - limits and tiers, times, addresses", async () => { let stoId = 3; - await I_USDTieredSTO_Array[stoId].modifyLimits(new BigNumber(1 * 10 ** 18), BigNumber(15 * 10 ** 18), { from: ISSUER }); + await I_USDTieredSTO_Array[stoId].modifyLimits(new BN(1).mul(e18), new BN(15).mul(e18), { from: ISSUER }); assert.equal( - (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), - BigNumber(15 * 10 ** 18).toNumber(), + (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toString(), + new BN(15).mul(e18).toString(), "STO Configuration doesn't set as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), - BigNumber(1 * 10 ** 18).toNumber(), + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toString(), + new BN(1).mul(e18).toString(), "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)], + [new BN(15).mul(e18)], + [new BN(13).mul(e18)], + [new BN(1500).mul(e18)], + [new BN(1500).mul(e18)], { from: ISSUER } ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(0))[0].toNumber(), - BigNumber(15 * 10 ** 18).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[0].toString(), + new BN(15).mul(e18).toString(), "STO Configuration doesn't set as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(0))[1].toNumber(), - BigNumber(13 * 10 ** 18).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[1].toString(), + new BN(13).mul(e18).toString(), "STO Configuration doesn't set as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(0))[2], - BigNumber(15 * 10 ** 20).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[2].toString(), + new BN(1500).mul(e18).toString(), "STO Configuration doesn't set as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(0))[3], - BigNumber(15 * 10 ** 20).toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(0))[3].toString(), + new BN(1500).mul(e18).toString(), "STO Configuration doesn't set as expected" ); - let tempTime1 = latestTime() + duration.days(0.1); - let tempTime2 = latestTime() + duration.days(0.2); + let tempTime1 = new BN(currentTime).add(new BN(duration.days(0.1))); + let tempTime2 = new BN(currentTime).add(new BN(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].modifyTimes(new BN(tempTime1), new BN(tempTime2), { from: ISSUER }); + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()).toString(), tempTime1.toString(), "STO Configuration doesn't set as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()).toString(), tempTime2.toString(), "STO Configuration doesn't set as expected"); await I_USDTieredSTO_Array[stoId].modifyAddresses( "0x0000000000000000000000000400000000000000", @@ -949,11 +961,7 @@ contract("USDTieredSTO", accounts => { "0x0000000000000000000003000000000000000000", "STO Configuration doesn't set as expected" ); - assert.equal( - await I_USDTieredSTO_Array[stoId].usdToken.call(), - address_zero, - "STO Configuration doesn't set as expected" - ); + assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(), address_zero, "STO Configuration doesn't set as expected"); }); it("Should fail to change config after endTime", async () => { @@ -964,22 +972,20 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].modifyFunding([0, 1], { from: ISSUER })); - await catchRevert( - I_USDTieredSTO_Array[stoId].modifyLimits(new BigNumber(15 * 10 ** 18), BigNumber(1 * 10 ** 18), { from: ISSUER }) - ); + await catchRevert(I_USDTieredSTO_Array[stoId].modifyLimits(new BN(15).mul(e18), new BN(1).mul(e18), { from: ISSUER })); await catchRevert( I_USDTieredSTO_Array[stoId].modifyTiers( - [BigNumber(15 * 10 ** 18)], - [BigNumber(13 * 10 ** 18)], - [BigNumber(15 * 10 ** 20)], - [BigNumber(15 * 10 ** 20)], + [new BN(15).mul(e18)], + [new BN(13).mul(e18)], + [new BN(1500).mul(e18)], + [new BN(1500).mul(e18)], { from: ISSUER } ) ); - let tempTime1 = latestTime(); - let tempTime2 = latestTime() + duration.days(3); + let tempTime1 = await latestTime(); + let tempTime2 = await latestTime() + duration.days(3); await catchRevert(I_USDTieredSTO_Array[stoId].modifyTimes(tempTime1, tempTime2, { from: ISSUER })); @@ -1004,8 +1010,8 @@ contract("USDTieredSTO", accounts => { 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 fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let whitelisted = true; @@ -1019,13 +1025,13 @@ contract("USDTieredSTO", accounts => { 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 + let investment_ETH = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH + let investment_POLY = new BN(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 + let investment_DAI = new BN(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); @@ -1050,8 +1056,8 @@ contract("USDTieredSTO", accounts => { let snapId = await takeSnapshot(); // // Whitelist - // let fromTime = latestTime(); - // let toTime = latestTime() + duration.days(15); + // let fromTime = await latestTime(); + // let toTime = await latestTime() + duration.days(15); // let expiryTime = toTime + duration.days(100); // let whitelisted = true; // @@ -1065,13 +1071,13 @@ contract("USDTieredSTO", accounts => { 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 + let investment_ETH = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH + let investment_POLY = new BN(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 + let investment_DAI = new BN(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); @@ -1104,8 +1110,8 @@ contract("USDTieredSTO", accounts => { let snapId = await takeSnapshot(); // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let whitelisted = true; @@ -1118,7 +1124,7 @@ contract("USDTieredSTO", accounts => { // Set as accredited await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - let investment_USD = new BigNumber(2).mul(10 ** 18); + let investment_USD = new BN(2).mul(e18); 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; @@ -1159,8 +1165,8 @@ contract("USDTieredSTO", accounts => { let snapId = await takeSnapshot(); // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let whitelisted = true; @@ -1178,14 +1184,14 @@ contract("USDTieredSTO", accounts => { 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 + let investment_ETH = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH + let investment_POLY = new BN(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 + let investment_DAI = new BN(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); @@ -1229,8 +1235,8 @@ contract("USDTieredSTO", accounts => { let snapId = await takeSnapshot(); // Whitelist - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let whitelisted = true; @@ -1246,13 +1252,13 @@ contract("USDTieredSTO", accounts => { 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 + let investment_ETH = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH + let investment_POLY = new BN(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 + let investment_DAI = new BN(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); @@ -1284,8 +1290,8 @@ contract("USDTieredSTO", accounts => { let snapId = await takeSnapshot(); // Whitelist - let fromTime = latestTime(); - let toTime = latestTime(); + let fromTime = await latestTime(); + let toTime = await latestTime(); let expiryTime = toTime + duration.days(100); let whitelisted = true; @@ -1308,13 +1314,13 @@ contract("USDTieredSTO", accounts => { await catchRevert(I_USDTieredSTO_Array[stoId].finalize({ 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 + let investment_ETH = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH + let investment_POLY = new BN(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 + let investment_DAI = new BN(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); @@ -1352,8 +1358,8 @@ contract("USDTieredSTO", accounts => { it("should whitelist ACCREDITED1 and NONACCREDITED1", async () => { let stoId = 0; - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let whitelisted = true; @@ -1402,23 +1408,23 @@ contract("USDTieredSTO", accounts => { let stoId = 0; let tierId = 0; - let investment_Token = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await web3.eth.sendTransaction({ @@ -1426,101 +1432,101 @@ contract("USDTieredSTO", accounts => { to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, - gas: 1000000 + gas: 7000000 }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey + tx1.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.gasUsed)); + console.log(" Gas fallback purchase: ".grey + new BN(tx1.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedUSD.toString(), init_RaisedUSD.add(investment_USD).toString(), "Raised USD not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toString(), init_RaisedDAI.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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].investorCount.call()).toString(), 1, "Investor count not changed as expected"); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), - investment_Token.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSold()).toString(), + investment_Token.toString(), "getTokensSold not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), - investment_Token.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toString(), + investment_Token.toString(), "getTokensMinted not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), - investment_Token.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toString(), + investment_Token.toString(), "getTokensSoldForETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), - 0, + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toString(), + new BN(0), "getTokensSoldForPOLY not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), - investment_USD.toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toString(), + investment_USD.toString(), "investorInvestedUSD not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), - investment_ETH.toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toString(), + investment_ETH.toString(), "investorInvestedETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), - 0, + (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toString(), + new BN(0), "investorInvestedPOLY not changed as expected" ); }); @@ -1529,22 +1535,22 @@ contract("USDTieredSTO", accounts => { let stoId = 0; let tierId = 0; - let investment_Token = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { @@ -1552,68 +1558,68 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toString(), init_RaisedDAI.toString(), "Raised DAI not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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 = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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); @@ -1623,15 +1629,15 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -1639,60 +1645,60 @@ contract("USDTieredSTO", accounts => { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "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_RaisedDAI.toString(), init_RaisedDAI.toString(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "Wallet POLY Balance not changed as expected" ); }); @@ -1701,7 +1707,7 @@ contract("USDTieredSTO", accounts => { let stoId = 0; let tierId = 0; - let investment_Token = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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); @@ -1712,16 +1718,16 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let init_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); @@ -1730,64 +1736,64 @@ contract("USDTieredSTO", accounts => { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithUSD: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithUSD: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(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(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_InvestorDAIBal.toNumber(), - init_InvestorDAIBal.sub(investment_DAI).toNumber(), + final_InvestorDAIBal.toString(), + init_InvestorDAIBal.sub(investment_DAI).toString(), "Investor DAI Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toString(), init_RaisedDAI.add(investment_DAI).toString(), "Raised POLY not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "Wallet POLY Balance not changed as expected"); assert.equal( - final_WalletDAIBal.toNumber(), - init_WalletDAIBal.add(investment_DAI).toNumber(), + final_WalletDAIBal.toString(), + init_WalletDAIBal.add(investment_DAI).toString(), "Wallet DAI Balance not changed as expected" ); }); @@ -1798,21 +1804,21 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - let investment_Token = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await web3.eth.sendTransaction({ @@ -1820,82 +1826,82 @@ contract("USDTieredSTO", accounts => { to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, - gas: 1000000 + gas: 7000000 }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey + tx1.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.gasUsed)); + console.log(" Gas fallback purchase: ".grey + new BN(tx1.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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 = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { @@ -1903,66 +1909,66 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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 = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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); @@ -1981,14 +1987,14 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -1996,96 +2002,96 @@ contract("USDTieredSTO", accounts => { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "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].investorCount.call()).toString(), 2, "Investor count not changed as expected"); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), - init_getTokensSold.add(investment_Token).toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSold()).toString(), + init_getTokensSold.add(investment_Token).toString(), "getTokensSold not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), - init_getTokensMinted.add(investment_Token).toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toString(), + init_getTokensMinted.add(investment_Token).toString(), "getTokensMinted not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), - init_getTokensSoldForETH.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toString(), + init_getTokensSoldForETH.toString(), "getTokensSoldForETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), - init_getTokensSoldForPOLY.add(investment_Token).toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toString(), + init_getTokensSoldForPOLY.add(investment_Token).toString(), "getTokensSoldForPOLY not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), - init_investorInvestedUSD.add(investment_USD).toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toString(), + init_investorInvestedUSD.add(investment_USD).toString(), "investorInvestedUSD not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), - init_investorInvestedETH.toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toString(), + init_investorInvestedETH.toString(), "investorInvestedETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), - init_investorInvestedPOLY.add(investment_POLY).toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toString(), + init_investorInvestedPOLY.add(investment_POLY).toString(), "investorInvestedPOLY not changed as expected" ); }); @@ -2093,11 +2099,11 @@ contract("USDTieredSTO", accounts => { 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)], { + console.log("Current investment: " + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toString()); + await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(new BN(2))], { from: ISSUER }); - console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toNumber()); + console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toString()); }); it("should successfully buy a partial amount and refund balance when reaching NONACCREDITED cap", async () => { @@ -2114,20 +2120,20 @@ contract("USDTieredSTO", accounts => { 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()); + console.log("Expected refund in tokens: " + refund_Token.toString()); let snap = await takeSnapshot(); let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy with ETH @@ -2136,79 +2142,79 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), + final_TokenSupply.toString(), init_TokenSupply .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), + final_InvestorTokenBal.toString(), init_InvestorTokenBal .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) .add(refund_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), + final_STOTokenSold.toString(), init_STOTokenSold .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); assert.equal( - final_RaisedETH.toNumber(), + final_RaisedETH.toString(), init_RaisedETH .add(investment_ETH) .sub(refund_ETH) - .toNumber(), + .toString(), "Raised ETH not changed as expected" ); - assert.equal(final_RaisedPOLY.toNumber(), init_RaisedPOLY.toNumber(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), + final_WalletETHBal.toString(), init_WalletETHBal .add(investment_ETH) .sub(refund_ETH) - .toNumber(), + .toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "Wallet POLY Balance not changed as expected"); await revertToSnapshot(snap); @@ -2217,14 +2223,14 @@ contract("USDTieredSTO", accounts => { init_TokenSupply = await I_SecurityToken.totalSupply(); init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + init_InvestorETHBal = new BN(await web3.eth.getBalance(NONACCREDITED1)); init_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); init_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - init_STOETHBal = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -2232,76 +2238,76 @@ contract("USDTieredSTO", accounts => { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); final_TokenSupply = await I_SecurityToken.totalSupply(); final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + final_InvestorETHBal = new BN(await web3.eth.getBalance(NONACCREDITED1)); final_InvestorPOLYBal = await I_PolyToken.balanceOf(NONACCREDITED1); final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); - final_STOETHBal = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), + final_TokenSupply.toString(), init_TokenSupply .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), + final_InvestorTokenBal.toString(), init_InvestorTokenBal .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), init_InvestorPOLYBal .sub(investment_POLY) .add(refund_POLY) - .toNumber(), + .toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), + final_STOTokenSold.toString(), init_STOTokenSold .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), + final_RaisedPOLY.toString(), init_RaisedPOLY .add(investment_POLY) .sub(refund_POLY) - .toNumber(), + .toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), + final_WalletPOLYBal.toString(), init_WalletPOLYBal .add(investment_POLY) .sub(refund_POLY) - .toNumber(), + .toString(), "Wallet POLY Balance not changed as expected" ); }); @@ -2310,7 +2316,7 @@ contract("USDTieredSTO", accounts => { let stoId = 0; let tierId = 0; - let investment_Token = new BigNumber(50).mul(10 ** 18); + let investment_Token = new BN(50).mul(e18); 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); @@ -2334,16 +2340,16 @@ contract("USDTieredSTO", accounts => { let tierId; // set new exchange rates - let high_USDETH = new BigNumber(1000).mul(10 ** 18); // 1000 USD per ETH - let high_USDPOLY = new BigNumber(50).mul(10 ** 16); // 0.5 USD per POLY - let low_USDETH = new BigNumber(250).mul(10 ** 18); // 250 USD per ETH - let low_USDPOLY = new BigNumber(20).mul(10 ** 16); // 0.2 USD per POLY + let high_USDETH = new BN(1000).mul(e18); // 1000 USD per ETH + let high_USDPOLY = new BN(50).mul(e16); // 0.5 USD per POLY + let low_USDETH = new BN(250).mul(e18); // 250 USD per ETH + let low_USDPOLY = new BN(20).mul(e16); // 0.2 USD per POLY - let investment_USD = new 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 + let investment_USD = new BN(web3.utils.toWei("50")); // USD + let investment_ETH_high = investment_USD.div(high_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(e18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(e18); // 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 }); @@ -2399,12 +2405,12 @@ contract("USDTieredSTO", accounts => { let endTier = 1; assert.equal( - (await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), + (await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), startTier, "currentTier not changed as expected" ); - let delta_Token = new BigNumber(5).mul(10 ** 18); + let delta_Token = new BN(5).mul(e18); let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); @@ -2414,14 +2420,14 @@ contract("USDTieredSTO", accounts => { // Process investment let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { @@ -2429,62 +2435,62 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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"); + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), endTier, "currentTier not changed as expected"); }); it("should successfully buy across tiers for NONACCREDITED POLY", async () => { @@ -2493,12 +2499,12 @@ contract("USDTieredSTO", accounts => { let endTier = 2; assert.equal( - (await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), + (await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), startTier, "currentTier not changed as expected" ); - let delta_Token = new BigNumber(5).mul(10 ** 18); // Token + let delta_Token = new BN(5).mul(e18); // Token let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); @@ -2511,77 +2517,77 @@ contract("USDTieredSTO", accounts => { // Process investment let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(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 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "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"); + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), endTier, "currentTier not changed as expected"); }); it("should successfully buy across tiers for ACCREDITED ETH", async () => { @@ -2592,12 +2598,12 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); assert.equal( - (await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), + (await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), startTier, "currentTier not changed as expected" ); - let delta_Token = new BigNumber(5).mul(10 ** 18); // Token + let delta_Token = new BN(5).mul(e18); // Token let ethTier0 = await convert(stoId, startTier, false, "TOKEN", "ETH", delta_Token); let ethTier1 = await convert(stoId, endTier, false, "TOKEN", "ETH", delta_Token); @@ -2607,14 +2613,14 @@ contract("USDTieredSTO", accounts => { // Process investment let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { @@ -2622,62 +2628,62 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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"); + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), endTier, "currentTier not changed as expected"); }); it("should successfully buy across tiers for ACCREDITED DAI", async () => { @@ -2686,12 +2692,12 @@ contract("USDTieredSTO", accounts => { let endTier = 4; assert.equal( - (await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), + (await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), startTier, "currentTier not changed as expected" ); - let delta_Token = new BigNumber(5).mul(10 ** 18); // Token + let delta_Token = new BN(5).mul(e18); // Token let daiTier0 = await convert(stoId, startTier, false, "TOKEN", "USD", delta_Token); let daiTier1 = await convert(stoId, endTier, false, "TOKEN", "USD", delta_Token); @@ -2704,83 +2710,83 @@ contract("USDTieredSTO", accounts => { // Process investment let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(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 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithUSD: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithUSD: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(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(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_InvestorDAIBal.toNumber(), - init_InvestorDAIBal.sub(investment_DAI).toNumber(), + final_InvestorDAIBal.toString(), + init_InvestorDAIBal.sub(investment_DAI).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); + assert.equal(final_RaisedDAI.toString(), init_RaisedDAI.add(investment_DAI).toString(), "Raised DAI not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "Wallet POLY Balance not changed as expected"); assert.equal( - final_WalletDAIBal.toNumber(), - init_WalletDAIBal.add(investment_DAI).toNumber(), + final_WalletDAIBal.toString(), + init_WalletDAIBal.add(investment_DAI).toString(), "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"); + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), endTier, "currentTier not changed as expected"); }); it("should successfully buy across tiers for ACCREDITED POLY", async () => { @@ -2789,12 +2795,12 @@ contract("USDTieredSTO", accounts => { let endTier = 5; assert.equal( - (await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), + (await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), startTier, "currentTier not changed as expected" ); - let delta_Token = new BigNumber(5).mul(10 ** 18); // Token + let delta_Token = new BN(5).mul(e18); // Token let polyTier0 = await convert(stoId, startTier, false, "TOKEN", "POLY", delta_Token); let polyTier1 = await convert(stoId, endTier, false, "TOKEN", "POLY", delta_Token); @@ -2807,77 +2813,77 @@ contract("USDTieredSTO", accounts => { // Process investment let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(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 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "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"); + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), endTier, "currentTier not changed as expected"); }); it("should buy out the rest of the sto", async () => { @@ -2885,9 +2891,9 @@ contract("USDTieredSTO", accounts => { let tierId = 5; let minted = (await I_USDTieredSTO_Array[stoId].tiers.call(tierId))[4]; - console.log(minted.toNumber() + ":" + _tokensPerTierTotal[stoId][tierId]); + console.log(minted.toString() + ":" + _tokensPerTierTotal[stoId][tierId]); let investment_Token = _tokensPerTierTotal[stoId][tierId].sub(minted); - console.log(investment_Token.toNumber()); + console.log(investment_Token.toString()); let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); let init_TokenSupply = await I_SecurityToken.totalSupply(); @@ -2906,28 +2912,28 @@ contract("USDTieredSTO", accounts => { let final_STOTokenSold = await I_USDTieredSTO_Array[stoId].getTokensSold(); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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"); + // assert.equal((await I_USDTieredSTO_Array[1].getTokensMinted()).toString(), _tokensPerTierTotal[1].reduce((a, b) => a + b, 0).toString(), "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 = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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); @@ -2983,16 +2989,16 @@ contract("USDTieredSTO", accounts => { let tierId = 4; // set new exchange rates - let high_USDETH = new BigNumber(1000).mul(10 ** 18); // 1000 USD per ETH - let high_USDPOLY = new BigNumber(50).mul(10 ** 16); // 0.5 USD per POLY - let low_USDETH = new BigNumber(250).mul(10 ** 18); // 250 USD per ETH - let low_USDPOLY = new BigNumber(20).mul(10 ** 16); // 0.2 USD per POLY + let high_USDETH = new BN(1000).mul(e18); // 1000 USD per ETH + let high_USDPOLY = new BN(50).mul(e16); // 0.5 USD per POLY + let low_USDETH = new BN(250).mul(e18); // 250 USD per ETH + let low_USDPOLY = new BN(20).mul(e16); // 0.2 USD per POLY - let investment_USD = new 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 + let investment_USD = new BN(web3.utils.toWei("50")); // USD + let investment_ETH_high = investment_USD.div(high_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(e18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(e18); // 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 }); @@ -3074,22 +3080,22 @@ contract("USDTieredSTO", accounts => { let stoId = 2; let tierId = 0; - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await web3.eth.sendTransaction({ @@ -3097,99 +3103,99 @@ contract("USDTieredSTO", accounts => { to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, - gas: 1000000 + gas: 7000000 }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey + tx1.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.gasUsed)); + console.log(" Gas fallback purchase: ".grey + new BN(tx1.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedUSD.toString(), init_RaisedUSD.add(investment_USD).toString(), "Raised USD not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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].investorCount.call()).toString(), 1, "Investor count not changed as expected"); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), - investment_Token.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSold()).toString(), + investment_Token.toString(), "getTokensSold not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), - investment_Token.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toString(), + investment_Token.toString(), "getTokensMinted not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), - investment_Token.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toString(), + investment_Token.toString(), "getTokensSoldForETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), - 0, + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toString(), + new BN(0), "getTokensSoldForPOLY not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toNumber(), - investment_USD.toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(NONACCREDITED1)).toString(), + investment_USD.toString(), "investorInvestedUSD not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toNumber(), - investment_ETH.toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, ETH)).toString(), + investment_ETH.toString(), "investorInvestedETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toNumber(), - 0, + (await I_USDTieredSTO_Array[stoId].investorInvested.call(NONACCREDITED1, POLY)).toString(), + new BN(0), "investorInvestedPOLY not changed as expected" ); }); @@ -3198,21 +3204,21 @@ contract("USDTieredSTO", accounts => { let stoId = 2; let tierId = 0; - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(NONACCREDITED1, { @@ -3220,66 +3226,66 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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 = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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); @@ -3289,14 +3295,14 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -3304,58 +3310,58 @@ contract("USDTieredSTO", accounts => { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "Wallet POLY Balance not changed as expected" ); }); @@ -3366,21 +3372,21 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await web3.eth.sendTransaction({ @@ -3388,82 +3394,82 @@ contract("USDTieredSTO", accounts => { to: I_USDTieredSTO_Array[stoId].address, value: investment_ETH, gasPrice: GAS_PRICE, - gas: 1000000 + gas: 7000000 }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.gasUsed); - console.log(" Gas fallback purchase: ".grey + tx1.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.gasUsed)); + console.log(" Gas fallback purchase: ".grey + new BN(tx1.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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 = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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 = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let tx1 = await I_USDTieredSTO_Array[stoId].buyWithETH(ACCREDITED1, { @@ -3471,66 +3477,66 @@ contract("USDTieredSTO", accounts => { value: investment_ETH, gasPrice: GAS_PRICE }); - let gasCost1 = new BigNumber(GAS_PRICE).mul(tx1.receipt.gasUsed); - console.log(" Gas buyWithETH: ".grey + tx1.receipt.gasUsed.toString().grey); + let gasCost1 = new BN(GAS_PRICE).mul(new BN(tx1.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(tx1.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), + final_InvestorETHBal.toString(), init_InvestorETHBal .sub(gasCost1) .sub(investment_ETH) - .toNumber(), + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.add(investment_ETH).toString(), "Raised ETH not changed as expected"); + assert.equal(final_RaisedPOLY.toString(), init_RaisedPOLY.toString(), "Raised POLY not changed as expected"); assert.equal( - final_WalletETHBal.toNumber(), - init_WalletETHBal.add(investment_ETH).toNumber(), + final_WalletETHBal.toString(), + init_WalletETHBal.add(investment_ETH).toString(), "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_WalletPOLYBal.toString(), init_WalletPOLYBal.toString(), "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 = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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); @@ -3549,14 +3555,14 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -3564,96 +3570,96 @@ contract("USDTieredSTO", accounts => { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "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].investorCount.call()).toString(), 2, "Investor count not changed as expected"); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSold()).toNumber(), - init_getTokensSold.add(investment_Token).toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSold()).toString(), + init_getTokensSold.add(investment_Token).toString(), "getTokensSold not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toNumber(), - init_getTokensMinted.add(investment_Token).toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensMinted()).toString(), + init_getTokensMinted.add(investment_Token).toString(), "getTokensMinted not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toNumber(), - init_getTokensSoldForETH.toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(ETH)).toString(), + init_getTokensSoldForETH.toString(), "getTokensSoldForETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toNumber(), - init_getTokensSoldForPOLY.add(investment_Token).toNumber(), + (await I_USDTieredSTO_Array[stoId].getTokensSoldFor(POLY)).toString(), + init_getTokensSoldForPOLY.add(investment_Token).toString(), "getTokensSoldForPOLY not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toNumber(), - init_investorInvestedUSD.add(investment_USD).toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvestedUSD.call(ACCREDITED1)).toString(), + init_investorInvestedUSD.add(investment_USD).toString(), "investorInvestedUSD not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toNumber(), - init_investorInvestedETH.toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, ETH)).toString(), + init_investorInvestedETH.toString(), "investorInvestedETH not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toNumber(), - init_investorInvestedPOLY.add(investment_POLY).toNumber(), + (await I_USDTieredSTO_Array[stoId].investorInvested.call(ACCREDITED1, POLY)).toString(), + init_investorInvestedPOLY.add(investment_POLY).toString(), "investorInvestedPOLY not changed as expected" ); }); @@ -3677,14 +3683,14 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -3692,89 +3698,89 @@ contract("USDTieredSTO", accounts => { from: NONACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(NONACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(NONACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), + final_TokenSupply.toString(), init_TokenSupply .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), + final_InvestorTokenBal.toString(), init_InvestorTokenBal .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), init_InvestorPOLYBal .sub(investment_POLY) .add(refund_POLY) - .toNumber(), + .toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), + final_STOTokenSold.toString(), init_STOTokenSold .add(investment_Token) .sub(refund_Token) - .toNumber(), + .toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), + final_RaisedPOLY.toString(), init_RaisedPOLY .add(investment_POLY) .sub(refund_POLY) - .toNumber(), + .toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), + final_WalletPOLYBal.toString(), init_WalletPOLYBal .add(investment_POLY) .sub(refund_POLY) - .toNumber(), + .toString(), "Wallet POLY Balance not changed as expected" ); }); 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}); + await I_SecurityToken.changeGranularity(e18, { 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_Tokens = new BN(1050).mul(e16); let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Tokens); - let refund_Tokens = (new BigNumber(0.5)).mul(10 ** 18); + let refund_Tokens = new BN(50).mul(e16); let refund_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", refund_Tokens); await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); @@ -3782,185 +3788,187 @@ contract("USDTieredSTO", accounts => { 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_InvestorETHBal = new BN(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_STOETHBal = new BN(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_WalletETHBal = new BN(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]; + 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 gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(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_InvestorETHBal = new BN(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_STOETHBal = new BN(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_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), + final_TokenSupply.toString(), init_TokenSupply .add(investment_Tokens) .sub(refund_Tokens) - .toNumber(), + .toString(), "Token Supply not changed as expected" ); + assert.equal(tokensToMint.toString(), investment_Tokens.sub(refund_Tokens).toString(), "View function returned incorrect data"); assert.equal( - tokensToMint.toNumber(), - investment_Tokens.sub(refund_Tokens).toNumber(), - "View function returned incorrect data" - ); - assert.equal( - final_InvestorTokenBal.toNumber(), + final_InvestorTokenBal.toString(), init_InvestorTokenBal .add(investment_Tokens) .sub(refund_Tokens) - .toNumber(), + .toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), + final_InvestorPOLYBal.toString(), init_InvestorPOLYBal .sub(investment_POLY) .add(refund_POLY) - .toNumber(), + .toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), + final_STOTokenSold.toString(), init_STOTokenSold .add(investment_Tokens) .sub(refund_Tokens) - .toNumber(), + .toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), + final_RaisedPOLY.toString(), init_RaisedPOLY .add(investment_POLY) .sub(refund_POLY) - .toNumber(), + .toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), + final_WalletPOLYBal.toString(), init_WalletPOLYBal .add(investment_POLY) .sub(refund_POLY) - .toNumber(), + .toString(), "Wallet POLY Balance not changed as expected" ); - await I_SecurityToken.changeGranularity(1, {from: ISSUER}); + 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}); + await I_SecurityToken.changeGranularity(e18, { from: ISSUER }); let stoId = 4; let tierId = 0; - let investment_Tokens = BigNumber(10.5).mul(10**18); + let investment_Tokens = new BN(1050).mul(e16); let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Tokens); - let refund_Tokens = BigNumber(0.5).mul(10**18); + let refund_Tokens = new BN(50).mul(e16); 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); - let init_InvestorETHBal = BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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_STOETHBal = new BN(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 gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithETH: ".grey + new BN(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_InvestorETHBal = new BN(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_STOETHBal = new BN(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(), + final_TokenSupply.toString(), init_TokenSupply .add(investment_Tokens) .sub(refund_Tokens) - .toNumber(), + .toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), + final_InvestorTokenBal.toString(), init_InvestorTokenBal .add(investment_Tokens) .sub(refund_Tokens) - .toNumber(), + .toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(investment_ETH).sub(gasCost2).add(refund_ETH).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal + .sub(investment_ETH) + .sub(gasCost2) + .add(refund_ETH) + .toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), + final_STOTokenSold.toString(), init_STOTokenSold .add(investment_Tokens) .sub(refund_Tokens) - .toNumber(), + .toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY, - "Raised POLY not changed as expected" + final_RaisedETH.toString(), + init_RaisedETH + .add(investment_ETH) + .sub(refund_ETH) + .toString(), + "Raised ETH not changed as expected" ); - await I_SecurityToken.changeGranularity(1, {from: ISSUER}); + assert.equal(final_RaisedPOLY.toString(), 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; - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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); @@ -3985,24 +3993,28 @@ contract("USDTieredSTO", accounts => { 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_Tokens = new BN(e18); 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); + const minTokens = new BN(1000).mul(e18); 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 - })); + 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 () => { @@ -4010,18 +4022,18 @@ contract("USDTieredSTO", accounts => { let tierId = 0; // set new exchange rates - let high_USDETH = new BigNumber(1000).mul(10 ** 18); // 1000 USD per ETH - let high_USDPOLY = new BigNumber(50).mul(10 ** 16); // 0.5 USD per POLY - let low_USDETH = new BigNumber(250).mul(10 ** 18); // 250 USD per ETH - let low_USDPOLY = new BigNumber(20).mul(10 ** 16); // 0.2 USD per POLY + let high_USDETH = new BN(1000).mul(e18); // 1000 USD per ETH + let high_USDPOLY = new BN(50).mul(e16); // 0.5 USD per POLY + let low_USDETH = new BN(250).mul(e18); // 250 USD per ETH + let low_USDPOLY = new BN(20).mul(e16); // 0.2 USD per POLY - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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 + let investment_ETH_high = investment_USD.div(high_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(e18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(e18); // 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 }); @@ -4077,12 +4089,12 @@ contract("USDTieredSTO", accounts => { let endTier = 1; assert.equal( - (await I_USDTieredSTO_Array[stoId].currentTier.call()).toNumber(), + (await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), startTier, "currentTier not changed as expected" ); - let delta_Token = new BigNumber(5).mul(10 ** 18); // Token + let delta_Token = new BN(5).mul(e18); // 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 @@ -4101,7 +4113,7 @@ contract("USDTieredSTO", accounts => { 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()); + assert.equal(Tier0Minted.toString(), Tier0Token.sub(delta_Token).toString()); await I_PolyToken.getTokens(investment_POLY, ACCREDITED1); await I_PolyToken.approve(I_USDTieredSTO_Array[stoId].address, investment_POLY, { from: ACCREDITED1 }); @@ -4109,87 +4121,87 @@ contract("USDTieredSTO", accounts => { // Process investment let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(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 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "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"); + assert.equal((await I_USDTieredSTO_Array[stoId].currentTier.call()).toString(), endTier, "currentTier not changed as expected"); }); it("should successfully buy across the discount cap", async () => { let stoId = 2; let tierId = 1; - let discount_Token = new BigNumber(20).mul(10 ** 18); + let discount_Token = new BN(20).mul(e18); let discount_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", discount_Token); - let regular_Token = new BigNumber(10).mul(10 ** 18); + let regular_Token = new BN(10).mul(e18); let regular_POLY = await convert(stoId, tierId, false, "TOKEN", "POLY", regular_Token); let investment_Token = discount_Token.add(regular_Token); @@ -4200,14 +4212,14 @@ contract("USDTieredSTO", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let init_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); // Buy With POLY @@ -4215,58 +4227,58 @@ contract("USDTieredSTO", accounts => { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); let final_TokenSupply = await I_SecurityToken.totalSupply(); let final_InvestorTokenBal = await I_SecurityToken.balanceOf(ACCREDITED1); - let final_InvestorETHBal = new BigNumber(await web3.eth.getBalance(ACCREDITED1)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); assert.equal( - final_TokenSupply.toNumber(), - init_TokenSupply.add(investment_Token).toNumber(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_InvestorETHBal.toNumber(), - init_InvestorETHBal.sub(gasCost2).toNumber(), + final_InvestorETHBal.toString(), + init_InvestorETHBal.sub(gasCost2).toString(), "Investor ETH Balance not changed as expected" ); assert.equal( - final_InvestorPOLYBal.toNumber(), - init_InvestorPOLYBal.sub(investment_POLY).toNumber(), + final_InvestorPOLYBal.toString(), + init_InvestorPOLYBal.sub(investment_POLY).toString(), "Investor POLY Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "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_STOETHBal.toString(), init_STOETHBal.toString(), "STO ETH Balance not changed as expected"); + assert.equal(final_STOPOLYBal.toString(), init_STOPOLYBal.toString(), "STO POLY Balance not changed as expected"); + assert.equal(final_RaisedETH.toString(), init_RaisedETH.toString(), "Raised ETH not changed as expected"); assert.equal( - final_RaisedPOLY.toNumber(), - init_RaisedPOLY.add(investment_POLY).toNumber(), + final_RaisedPOLY.toString(), + init_RaisedPOLY.add(investment_POLY).toString(), "Raised POLY not changed as expected" ); - assert.equal(final_WalletETHBal.toNumber(), init_WalletETHBal.toNumber(), "Wallet ETH Balance not changed as expected"); + assert.equal(final_WalletETHBal.toString(), init_WalletETHBal.toString(), "Wallet ETH Balance not changed as expected"); assert.equal( - final_WalletPOLYBal.toNumber(), - init_WalletPOLYBal.add(investment_POLY).toNumber(), + final_WalletPOLYBal.toString(), + init_WalletPOLYBal.add(investment_POLY).toString(), "Wallet POLY Balance not changed as expected" ); }); @@ -4291,26 +4303,26 @@ contract("USDTieredSTO", accounts => { from: ACCREDITED1, gasPrice: GAS_PRICE }); - let gasCost2 = new BigNumber(GAS_PRICE).mul(tx2.receipt.gasUsed); - console.log(" Gas buyWithPOLY: ".grey + tx2.receipt.gasUsed.toString().grey); + let gasCost2 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); + console.log(" Gas buyWithPOLY: ".grey + new BN(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(), + final_TokenSupply.toString(), + init_TokenSupply.add(investment_Token).toString(), "Token Supply not changed as expected" ); assert.equal( - final_InvestorTokenBal.toNumber(), - init_InvestorTokenBal.add(investment_Token).toNumber(), + final_InvestorTokenBal.toString(), + init_InvestorTokenBal.add(investment_Token).toString(), "Investor Token Balance not changed as expected" ); assert.equal( - final_STOTokenSold.toNumber(), - init_STOTokenSold.add(investment_Token).toNumber(), + final_STOTokenSold.toString(), + init_STOTokenSold.add(investment_Token).toString(), "STO Token Sold not changed as expected" ); }); @@ -4319,7 +4331,7 @@ contract("USDTieredSTO", accounts => { let stoId = 2; let tierId = 1; - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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); @@ -4359,18 +4371,18 @@ contract("USDTieredSTO", accounts => { let tierId = 1; // set new exchange rates - let high_USDETH = new BigNumber(1000).mul(10 ** 18); // 1000 USD per ETH - let high_USDPOLY = new BigNumber(50).mul(10 ** 16); // 0.5 USD per POLY - let low_USDETH = new BigNumber(250).mul(10 ** 18); // 250 USD per ETH - let low_USDPOLY = new BigNumber(20).mul(10 ** 16); // 0.2 USD per POLY + let high_USDETH = new BN(1000).mul(e18); // 1000 USD per ETH + let high_USDPOLY = new BN(50).mul(e16); // 0.5 USD per POLY + let low_USDETH = new BN(250).mul(e18); // 250 USD per ETH + let low_USDPOLY = new BN(20).mul(e16); // 0.2 USD per POLY - let investment_Token = new BigNumber(5).mul(10 ** 18); + let investment_Token = new BN(5).mul(e18); 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 + let investment_ETH_high = investment_USD.div(high_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_high = investment_USD.div(high_USDPOLY).mul(e18); // USD / USD/POLY = POLY + let investment_ETH_low = investment_USD.div(low_USDETH).mul(e18); // USD / USD/ETH = ETH + let investment_POLY_low = investment_USD.div(low_USDPOLY).mul(e18); // 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 }); @@ -4451,50 +4463,56 @@ contract("USDTieredSTO", accounts => { 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(), + (await I_USDTieredSTO_Array[0].investorCount.call()).toString(), + (await I_USDTieredSTO_Array[0].investorCount()).toString(), "Investor count not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[1].investorCount.call()).toNumber(), - (await I_USDTieredSTO_Array[1].investorCount()).toNumber(), + (await I_USDTieredSTO_Array[1].investorCount.call()).toString(), + (await I_USDTieredSTO_Array[1].investorCount()).toString(), "Investor count not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[2].investorCount.call()).toNumber(), - (await I_USDTieredSTO_Array[2].investorCount()).toNumber(), + (await I_USDTieredSTO_Array[2].investorCount.call()).toString(), + (await I_USDTieredSTO_Array[2].investorCount()).toString(), "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(), + (await I_USDTieredSTO_Array[0].fundsRaised.call(ETH)).toString(), + (await I_USDTieredSTO_Array[0].getRaised(0)).toString(), "getRaisedEther not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[0].fundsRaised.call(POLY)).toNumber(), - (await I_USDTieredSTO_Array[0].getRaised(1)).toNumber(), + (await I_USDTieredSTO_Array[0].fundsRaised.call(POLY)).toString(), + (await I_USDTieredSTO_Array[0].getRaised(1)).toString(), "getRaisedPOLY not changed as expected" ); assert.equal( - (await I_USDTieredSTO_Array[0].fundsRaisedUSD.call()).toNumber(), - (await I_USDTieredSTO_Array[0].fundsRaisedUSD()).toNumber(), + (await I_USDTieredSTO_Array[0].fundsRaisedUSD.call()).toString(), + (await I_USDTieredSTO_Array[0].fundsRaisedUSD()).toString(), "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 totalMinted = (await I_USDTieredSTO_Array[0].getTokensSoldByTier.call(0)).toString(); let individualMinted = await I_USDTieredSTO_Array[0].getTokensMintedByTier.call(0); - assert.equal(totalMinted, individualMinted[0].add(individualMinted[1]).add(individualMinted[2]).toNumber()); + assert.equal( + totalMinted, + individualMinted[0] + .add(individualMinted[1]) + .add(individualMinted[2]) + .toString() + ); }); it("should return correct tokens sold in token details", async () => { - let tokensSold = (await I_USDTieredSTO_Array[0].getTokensSold.call()).toNumber(); + let tokensSold = (await I_USDTieredSTO_Array[0].getTokensSold.call()).toString(); let tokenDetails = await I_USDTieredSTO_Array[0].getSTODetails.call(); - assert.equal(tokensSold, tokenDetails[7].toNumber()); + assert.equal(tokensSold, tokenDetails[7].toString()); }); }); @@ -4507,27 +4525,27 @@ contract("USDTieredSTO", accounts => { it("should get the right conversion for ETH to USD", async () => { // 20 ETH to 10000 USD - let ethInWei = new BigNumber(web3.utils.toWei("20", "ether")); + let ethInWei = new BN(web3.utils.toWei("20", "ether")); let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(ETH, ethInWei); assert.equal( - usdInWei.div(10 ** 18).toNumber(), + usdInWei.div(e18).toString(), ethInWei - .div(10 ** 18) - .mul(USDETH.div(10 ** 18)) - .toNumber() + .div(e18) + .mul(USDETH.div(e18)) + .toString() ); }); it("should get the right conversion for POLY to USD", async () => { // 40000 POLY to 10000 USD - let polyInWei = new BigNumber(web3.utils.toWei("40000", "ether")); + let polyInWei = new BN(web3.utils.toWei("40000", "ether")); let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(POLY, polyInWei); assert.equal( - usdInWei.div(10 ** 18).toNumber(), + usdInWei.toString(), polyInWei - .div(10 ** 18) - .mul(USDPOLY.div(10 ** 18)) - .toNumber() + .mul(USDPOLY) + .div(e18) + .toString() ); }); }); @@ -4535,27 +4553,24 @@ contract("USDTieredSTO", accounts => { describe("convertFromUSD", async () => { it("should get the right conversion for USD to ETH", async () => { // 10000 USD to 20 ETH - let usdInWei = new BigNumber(web3.utils.toWei("10000", "ether")); + let usdInWei = new BN(web3.utils.toWei("10000", "ether")); let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD(ETH, usdInWei); assert.equal( - ethInWei.div(10 ** 18).toNumber(), + ethInWei.div(e18).toString(), usdInWei - .div(10 ** 18) - .div(USDETH.div(10 ** 18)) - .toNumber() + .div(e18) + .div(USDETH.div(e18)) + .toString() ); }); it("should get the right conversion for USD to POLY", async () => { // 10000 USD to 40000 POLY - let usdInWei = new BigNumber(web3.utils.toWei("10000", "ether")); + let usdInWei = new BN(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() + polyInWei.toString(), + usdInWei.mul(e18).div(USDPOLY).toString() ); }); }); @@ -4563,12 +4578,14 @@ 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.getSetupCost.call()).toNumber(), STOSetupCost); + assert.equal((await I_USDTieredSTOFactory.getSetupCost.call()).toString(), 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(), - "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.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.version.call(), "2.1.0"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index cee19785a..2e5fd4e5f 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -14,12 +14,12 @@ const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager") const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; 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 +//const TOLERANCE = 2; // Allow balances to be off by 2 WEI for rounding purposes -contract("USDTieredSTO Sim", accounts => { +contract("USDTieredSTO Sim", async (accounts) => { // Accounts Variable declaration let POLYMATH; let ISSUER; @@ -70,12 +70,12 @@ contract("USDTieredSTO Sim", accounts => { const STOKEY = 3; // Initial fee for ticker registry and security token registry - const REGFEE = web3.utils.toWei("250"); + const REGFEE = new BN(web3.utils.toWei("250")); const STOSetupCost = 0; // MockOracle USD prices - const USDETH = new BigNumber(500).mul(10 ** 18); // 500 USD/ETH - const USDPOLY = new BigNumber(25).mul(10 ** 16); // 0.25 USD/POLY + const USDETH = new BN(500).mul(new BN(10).pow(new BN(18))); // 500 USD/ETH + const USDPOLY = new BN(25).mul(new BN(10).pow(new BN(16))); // 0.25 USD/POLY // STO Configuration Arrays let _startTime = []; @@ -90,6 +90,9 @@ contract("USDTieredSTO Sim", accounts => { let _wallet = []; let _reserveWallet = []; let _usdToken = []; + + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; /* function configure( uint256 _startTime, @@ -161,11 +164,23 @@ contract("USDTieredSTO Sim", accounts => { }; function getRandomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; + let random = Math.floor(Math.random() * 10 ** 10); + return new BN(random).mul(new BN(max).add(new BN(1)).sub(new BN(min))).div(new BN(10).pow(new BN(10))); } + function minBN(a, b) { + if (a.lt(b)) + return a; + else + return b; + } + + let currentTime; + let e18 = new BN(10).pow(new BN(18)); + let e16 = new BN(10).pow(new BN(16)); + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); POLYMATH = accounts[0]; ISSUER = accounts[1]; WALLET = accounts[2]; @@ -198,14 +213,14 @@ contract("USDTieredSTO Sim", accounts => { I_STRGetter ] = instances; - I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); + I_DaiToken = await PolyTokenFaucet.new({ from: POLYMATH }); - // STEP 5: Deploy the USDTieredSTOFactory - [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, STOSetupCost); + // STEP 5: Deploy the USDTieredSTOFactory + [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, STOSetupCost); // 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 + I_USDOracle = await MockOracle.new(address_zero, web3.utils.fromAscii("ETH"), web3.utils.fromAscii("USD"), USDETH, { from: POLYMATH }); // 500 dollars per POLY + I_POLYOracle = await MockOracle.new(I_PolyToken.address, web3.utils.fromAscii("POLY"), web3.utils.fromAscii("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 }); @@ -241,13 +256,13 @@ contract("USDTieredSTO Sim", accounts => { 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[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), TMKEY); @@ -256,20 +271,20 @@ contract("USDTieredSTO Sim", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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(new BigNumber(10 * 10 ** 18)); // 20 USD - _minimumInvestmentUSD.push(new BigNumber(0)); // 1 wei USD + _startTime.push(new BN(currentTime).add(new BN(duration.days(2)))); + _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(duration.days(100))))); + _ratePerTier.push([new BN(50).mul(e16), new BN(130).mul(e16), new BN(170).mul(e16)]); // [ 0.05 USD/Token, 0.10 USD/Token, 0.15 USD/Token ] + _ratePerTierDiscountPoly.push([new BN(50).mul(e16), new BN(80).mul(e16), new BN(130).mul(e16)]); // [ 0.05 USD/Token, 0.08 USD/Token, 0.13 USD/Token ] + _tokensPerTierTotal.push([new BN(200).mul(e18), new BN(500).mul(e18), new BN(300).mul(e18)]); // [ 1000 Token, 2000 Token, 1500 Token ] + _tokensPerTierDiscountPoly.push([new BN(0), new BN(50).mul(e18), new BN(300).mul(e18)]); // [ 0 Token, 1000 Token, 1500 Token ] + _nonAccreditedLimitUSD.push(new BN(10).mul(e18)); // 20 USD + _minimumInvestmentUSD.push(new BN(0)); // 1 wei USD _fundRaiseTypes.push([0, 1, 2]); _wallet.push(WALLET); _reserveWallet.push(RESERVEWALLET); @@ -291,44 +306,44 @@ contract("USDTieredSTO Sim", accounts => { ]; 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 }); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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)); + I_USDTieredSTO_Array.push(await 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"); + assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()).toString(), _startTime[stoId].toString(), "Incorrect _startTime in config"); + assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()).toString(), _endTime[stoId].toString(), "Incorrect _endTime 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(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[0].toString(), + _ratePerTier[stoId][i].toString(), "Incorrect _ratePerTier in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toNumber(), - _ratePerTierDiscountPoly[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[1].toString(), + _ratePerTierDiscountPoly[stoId][i].toString(), "Incorrect _ratePerTierDiscountPoly in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toNumber(), - _tokensPerTierTotal[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[2].toString(), + _tokensPerTierTotal[stoId][i].toString(), "Incorrect _tokensPerTierTotal in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toNumber(), - _tokensPerTierDiscountPoly[stoId][i].toNumber(), + (await I_USDTieredSTO_Array[stoId].tiers.call(i))[3].toString(), + _tokensPerTierDiscountPoly[stoId][i].toString(), "Incorrect _tokensPerTierDiscountPoly in config" ); } assert.equal( - (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toNumber(), - _nonAccreditedLimitUSD[stoId].toNumber(), + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSD.call()).toString(), + _nonAccreditedLimitUSD[stoId].toString(), "Incorrect _nonAccreditedLimitUSD in config" ); assert.equal( - (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toNumber(), - _minimumInvestmentUSD[stoId].toNumber(), + (await I_USDTieredSTO_Array[stoId].minimumInvestmentUSD.call()).toString(), + _minimumInvestmentUSD[stoId].toString(), "Incorrect _minimumInvestmentUSD in config" ); assert.equal(await I_USDTieredSTO_Array[stoId].wallet.call(), _wallet[stoId], "Incorrect _wallet in config"); @@ -342,7 +357,7 @@ contract("USDTieredSTO Sim", accounts => { _tokensPerTierTotal[stoId].length, "Incorrect number of tiers" ); - assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); + assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, new BN(0), "Incorrect number of permissions"); }); it("Should successfully prepare the STO", async () => { @@ -352,8 +367,8 @@ contract("USDTieredSTO Sim", accounts => { await increaseTime(duration.days(3)); // Whitelist - let fromTime = latestTime() + duration.days(15); - let toTime = latestTime() + duration.days(15); + let fromTime = await latestTime() + duration.days(15); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let canBuyFromSTO = true; @@ -386,14 +401,15 @@ contract("USDTieredSTO Sim", accounts => { ---------------------------------------------------------- `); - let totalTokens = new BigNumber(0); + let totalTokens = new BN(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 = new BigNumber(0); + let tokensSold = new BN(0); while (true) { - switch (getRandomInt(0, 5)) { + let rn = getRandomInt(0, 5); + let rno = rn.toNumber(); + switch (rno) { case 0: // ACCREDITED1 await invest(ACCREDITED1, true); break; @@ -425,8 +441,8 @@ contract("USDTieredSTO Sim", accounts => { } 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("Tokens Sold: " + tokensSold.div(e18).toString()); + if (tokensSold.gte(totalTokens.sub(new BN(1)))) { console.log(`${tokensSold} tokens sold, simulation completed successfully!`.green); break; } @@ -439,33 +455,26 @@ contract("USDTieredSTO Sim", accounts => { 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); + USD_remaining = totalTokens.mul(new BN(2)); } let log_remaining = USD_remaining; let isPoly = Math.random() >= 0.33; let isDai = Math.random() >= 0.33; - let Token_counter = new BigNumber(getRandomInt(1 * 10 ** 10, 50 * 10 ** 10)).mul(10 ** 8); - let investment_USD = new BigNumber(0); - let investment_ETH = new BigNumber(0); - let investment_POLY = new BigNumber(0); - let investment_DAI = new BigNumber(0); - let investment_Token = new BigNumber(0); + let Token_counter = new BN(getRandomInt(new BN(1).mul(new BN(10).pow(new BN(10))), new BN(5).mul(new BN(10).pow(new BN(11))))).mul(new BN(10).pow(new BN(8))); + let investment_USD = new BN(0); + let investment_ETH = new BN(0); + let investment_POLY = new BN(0); + let investment_DAI = new BN(0); + let investment_Token = new BN(0); let Tokens_total = []; let Tokens_discount = []; for (var i = 0; i < _ratePerTier[stoId].length; i++) { - Tokens_total.push( - (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].tiers.call(i))[3].sub( - (await I_USDTieredSTO_Array[stoId].tiers.call(i))[5] - ) - ); + let tierData = await I_USDTieredSTO_Array[stoId].tiers.call(i); + Tokens_total.push(new BN(tierData[2]).sub(tierData[4])); + Tokens_discount.push(new BN(tierData[3]).sub(tierData[5])); } let tier = 0; @@ -478,25 +487,25 @@ contract("USDTieredSTO Sim", accounts => { let USD_overflow; let Token_overflow; - while (Token_counter.gt(0)) { + while (Token_counter.gt(new BN(0))) { if (tier == _ratePerTier[stoId].length) { break; } - if (Tokens_total[tier].gt(0)) { + if (Tokens_total[tier].gt(new BN(0))) { if (isPoly) { // 1. POLY and discount (consume up to cap then move to regular) - if (Tokens_discount[tier].gt(0)) { - Token_Tier = new BigNumber.min([Tokens_total[tier], Tokens_discount[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTierDiscountPoly[stoId][tier].div(10 ** 18)); + if (Tokens_discount[tier].gt(new BN(0))) { + Token_Tier = minBN(minBN(Tokens_total[tier], Tokens_discount[tier]), Token_counter); + USD_Tier = Token_Tier.mul(_ratePerTierDiscountPoly[stoId][tier]).div(e18); if (USD_Tier.gte(USD_remaining)) { USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10 ** 18).div(_ratePerTierDiscountPoly[stoId][tier]); + Token_overflow = USD_overflow.mul(e18).div(_ratePerTierDiscountPoly[stoId][tier]); USD_Tier = USD_Tier.sub(USD_overflow); Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = new BigNumber(0); + Token_counter = new BN(0); } - POLY_Tier = new BigNumber(USD_Tier.mul(10 ** 18).toFixed(0)); - POLY_Tier = POLY_Tier.div(USDPOLY).toFixed(0); + POLY_Tier = new BN(USD_Tier.mul(e18)); + POLY_Tier = POLY_Tier.div(USDPOLY); 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); @@ -506,18 +515,18 @@ contract("USDTieredSTO Sim", accounts => { 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 = new BigNumber.min([Tokens_total[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10 ** 18)); + if (Tokens_total[tier].gt(new BN(0)) && Token_counter.gt(new BN(0))) { + Token_Tier = minBN(Tokens_total[tier], Token_counter); + USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier]).div(e18); if (USD_Tier.gte(USD_remaining)) { USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10 ** 18).div(_ratePerTier[stoId][tier]); + Token_overflow = USD_overflow.mul(e18).div(_ratePerTier[stoId][tier]); USD_Tier = USD_Tier.sub(USD_overflow); Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = new BigNumber(0); + Token_counter = new BN(0); } - POLY_Tier = new BigNumber(USD_Tier.mul(10 ** 18).toFixed(0)); - POLY_Tier = POLY_Tier.div(USDPOLY).toFixed(0); + POLY_Tier = new BN(USD_Tier.mul(e18)); + POLY_Tier = POLY_Tier.div(USDPOLY); USD_remaining = USD_remaining.sub(USD_Tier); Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); Token_counter = Token_counter.sub(Token_Tier); @@ -527,16 +536,16 @@ contract("USDTieredSTO Sim", accounts => { } } else if (isDai) { // 3. DAI (consume up to cap then skip to next tier) - Token_Tier = new BigNumber.min([Tokens_total[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10 ** 18)); + Token_Tier = minBN(Tokens_total[tier], Token_counter); + USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier]).div(e18); if (USD_Tier.gte(USD_remaining)) { USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10 ** 18).div(_ratePerTier[stoId][tier]); + Token_overflow = USD_overflow.mul(e18).div(_ratePerTier[stoId][tier]); USD_Tier = USD_Tier.sub(USD_overflow); Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = new BigNumber(0); + Token_counter = new BN(0); } - DAI_Tier = USD_Tier.toFixed(0); + DAI_Tier = USD_Tier; USD_remaining = USD_remaining.sub(USD_Tier); Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); Token_counter = Token_counter.sub(Token_Tier); @@ -545,17 +554,16 @@ contract("USDTieredSTO Sim", accounts => { investment_DAI = investment_USD; } else { // 4. ETH (consume up to cap then skip to next tier) - Token_Tier = new BigNumber.min([Tokens_total[tier], Token_counter]); - USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier].div(10 ** 18)); + Token_Tier = minBN(Tokens_total[tier], Token_counter); + USD_Tier = Token_Tier.mul(_ratePerTier[stoId][tier]).div(e18); if (USD_Tier.gte(USD_remaining)) { USD_overflow = USD_Tier.sub(USD_remaining); - Token_overflow = USD_overflow.mul(10 ** 18).div(_ratePerTier[stoId][tier]); + Token_overflow = USD_overflow.mul(e18).div(_ratePerTier[stoId][tier]); USD_Tier = USD_Tier.sub(USD_overflow); Token_Tier = Token_Tier.sub(Token_overflow); - Token_counter = new BigNumber(0); + Token_counter = new BN(0); } - ETH_Tier = new BigNumber(USD_Tier.mul(10 ** 18).toFixed(0)); - ETH_Tier = ETH_Tier.div(USDETH).toFixed(0); + ETH_Tier = USD_Tier.mul(e18).div(USDETH); USD_remaining = USD_remaining.sub(USD_Tier); Tokens_total[tier] = Tokens_total[tier].sub(Token_Tier); Token_counter = Token_counter.sub(Token_Tier); @@ -564,7 +572,7 @@ contract("USDTieredSTO Sim", accounts => { investment_ETH = investment_ETH.add(ETH_Tier); } } - tier++; + tier = tier + 1; } await processInvestment( @@ -586,9 +594,9 @@ contract("USDTieredSTO Sim", accounts => { async function investFAIL(_investor) { let isPoly = Math.random() >= 0.3; let isDAI = Math.random() >= 0.3; - let investment_POLY = new BigNumber(40 * 10 ** 18); // 10 USD = 40 POLY - let investment_ETH = new BigNumber(0.02 * 10 ** 18); // 10 USD = 0.02 ETH - let investment_DAI = new BigNumber(10 * 10 ** 18); // 10 USD = DAI DAI + let investment_POLY = new BN(40).mul(e18); // 10 USD = 40 POLY + let investment_ETH = new BN(20).mul(e16); // 10 USD = 0.02 ETH + let investment_DAI = new BN(10).mul(e18); // 10 USD = DAI DAI if (isPoly) { await I_PolyToken.getTokens(investment_POLY, _investor); @@ -622,23 +630,23 @@ contract("USDTieredSTO Sim", accounts => { Tokens_discount, tokensSold ) { - investment_Token = new BigNumber(investment_Token.toFixed(0)); - investment_USD = new BigNumber(investment_USD.toFixed(0)); - investment_POLY = new BigNumber(investment_POLY.toFixed(0)); - investment_DAI = new BigNumber(investment_DAI.toFixed(0)); - investment_ETH = new BigNumber(investment_ETH.toFixed(0)); + investment_Token = new BN(investment_Token); + investment_USD = new BN(investment_USD); + investment_POLY = new BN(investment_POLY); + investment_DAI = new BN(investment_DAI); + investment_ETH = new BN(investment_ETH); console.log(` ------------------- New Investment ------------------- Investor: ${_investor} - N-A USD Remaining: ${log_remaining.div(10 ** 18)} + N-A USD Remaining: ${log_remaining} 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)} + Total Tokens Sold: ${tokensSold} + Token Investment: ${investment_Token} + USD Investment: ${investment_USD} + POLY Investment: ${investment_POLY} + DAI Investment: ${investment_DAI} + ETH Investment: ${investment_ETH} ------------------------------------------------------ `); @@ -654,69 +662,68 @@ contract("USDTieredSTO Sim", accounts => { let init_TokenSupply = await I_SecurityToken.totalSupply(); let init_InvestorTokenBal = await I_SecurityToken.balanceOf(_investor); - let init_InvestorETHBal = new BigNumber(await web3.eth.getBalance(_investor)); + let init_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let init_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let init_WalletETHBal = new BN(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 = new BigNumber(0); + let gasCost = new BN(0); - if (isPoly && investment_POLY.gt(10)) { + if (isPoly && investment_POLY.gt(new BN(10))) { tx = await I_USDTieredSTO_Array[stoId].buyWithPOLY(_investor, investment_POLY, { from: _investor, gasPrice: GAS_PRICE }); - gasCost = new BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); + gasCost = new BN(GAS_PRICE).mul(new BN(tx.receipt.gasUsed)); console.log( - `buyWithPOLY: ${investment_Token.div(10 ** 18)} tokens for ${investment_POLY.div(10 ** 18)} POLY by ${_investor}` + `buyWithPOLY: ${investment_Token.div(e18)} tokens for ${investment_POLY.div(e18)} POLY by ${_investor}` .yellow ); - } else if (isDai && investment_DAI.gt(10)) { + } else if (isDai && investment_DAI.gt(new BN(10))) { tx = await I_USDTieredSTO_Array[stoId].buyWithUSD(_investor, investment_DAI, { from: _investor, gasPrice: GAS_PRICE }); - gasCost = new BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); + gasCost = new BN(GAS_PRICE).mul(new BN(tx.receipt.gasUsed)); console.log( - `buyWithUSD: ${investment_Token.div(10 ** 18)} tokens for ${investment_DAI.div(10 ** 18)} DAI by ${_investor}` + `buyWithUSD: ${investment_Token.div(e18)} tokens for ${investment_DAI.div(e18)} DAI by ${_investor}` .yellow ); - } else if (investment_ETH.gt(0)) { + } else if (investment_ETH.gt(new BN(0))) { tx = await I_USDTieredSTO_Array[stoId].buyWithETH(_investor, { from: _investor, value: investment_ETH, gasPrice: GAS_PRICE }); - gasCost = new BigNumber(GAS_PRICE).mul(tx.receipt.gasUsed); + gasCost = new BN(GAS_PRICE).mul(new BN(tx.receipt.gasUsed)); console.log( - `buyWithETH: ${investment_Token.div(10 ** 18)} tokens for ${investment_ETH.div(10 ** 18)} ETH by ${_investor}` + `buyWithETH: ${investment_Token.div(e18)} tokens for ${investment_ETH.div(e18)} 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 = new BigNumber(await web3.eth.getBalance(_investor)); + let final_InvestorETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(I_USDTieredSTO_Array[stoId].address)); + let final_STOETHBal = new BN(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 = new BigNumber(await web3.eth.getBalance(WALLET)); + let final_WalletETHBal = new BN(await web3.eth.getBalance(WALLET)); let final_WalletPOLYBal = await I_PolyToken.balanceOf(WALLET); let final_WalletDAIBal = await I_DaiToken.balanceOf(WALLET); @@ -724,223 +731,56 @@ contract("USDTieredSTO Sim", accounts => { // 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" - ); + assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); + assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); + assertIsNear(final_InvestorETHBal, init_InvestorETHBal.sub(gasCost), "Investor ETH Balance not changed as expected" ); + assertIsNear(final_InvestorPOLYBal, init_InvestorPOLYBal.sub(investment_POLY), "Investor POLY Balance not changed as expected" ); + assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); + assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); + assertIsNear(final_STOPOLYBal, init_STOPOLYBal, "STO POLY Balance not changed as expected" ); + assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); + assertIsNear(final_RaisedETH, init_RaisedETH, "Raised ETH not changed as expected"); + assertIsNear(final_RaisedPOLY, init_RaisedPOLY.add(investment_POLY), "Raised POLY not changed as expected" ); + assertIsNear(final_WalletETHBal, init_WalletETHBal, "Wallet ETH Balance not changed as expected" ); + assertIsNear(final_WalletPOLYBal, init_WalletPOLYBal.add(investment_POLY), "Wallet POLY Balance not changed as expected" ); + } else if (isDai) { + assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); + assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); + assertIsNear(final_InvestorETHBal, init_InvestorETHBal.sub(gasCost), "Investor ETH Balance not changed as expected" ); + assertIsNear(final_InvestorDAIBal, init_InvestorDAIBal.sub(investment_DAI), "Investor DAI Balance not changed as expected" ); + assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); + assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); + assertIsNear(final_STODAIBal, init_STODAIBal, "STO DAI Balance not changed as expected" ); + assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); + assertIsNear(final_RaisedETH, init_RaisedETH, "Raised ETH not changed as expected"); + assertIsNear(final_RaisedDAI, init_RaisedDAI.add(investment_DAI), "Raised DAI not changed as expected" ); + assertIsNear(final_WalletETHBal, init_WalletETHBal, "Wallet ETH Balance not changed as expected" ); + assertIsNear(final_WalletDAIBal, init_WalletDAIBal.add(investment_DAI), "Wallet DAI Balance not changed as expected" ); + } else { + assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); + assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); + assertIsNear(final_InvestorETHBal, init_InvestorETHBal .sub(gasCost) .sub(investment_ETH) , "Investor ETH Balance not changed as expected" ); + assertIsNear(final_InvestorPOLYBal, init_InvestorPOLYBal, "Investor POLY Balance not changed as expected" ); + assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); + assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); + assertIsNear(final_STOPOLYBal, init_STOPOLYBal, "STO POLY Balance not changed as expected" ); + assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); + assertIsNear(final_RaisedETH, init_RaisedETH.add(investment_ETH), "Raised ETH not changed as expected" ); + assertIsNear(final_RaisedPOLY, init_RaisedPOLY, "Raised POLY not changed as expected" ); + assertIsNear(final_WalletETHBal, init_WalletETHBal.add(investment_ETH), "Wallet ETH Balance not changed as expected" ); + assertIsNear(final_WalletPOLYBal, init_WalletPOLYBal, "Wallet POLY Balance not changed as expected" ); } } }); }); }); -function near(x, y, message) { - assert.isAtMost(x, y); -} +function assertIsNear(a, b, reason) { + a = new BN(a); + b = new BN(b); + if (a.gt(b)) { + assert.isBelow(a.sub(b).toNumber(), 4, reason); + } else { + assert.isBelow(b.sub(a).toNumber(), 4, reason); + } +} \ No newline at end of file diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 0c4a06add..129116c26 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -7,8 +7,7 @@ import { deployDummySTOAndVerifyed, deployCappedSTOAndVerifyed, deployPresaleSTOAndVerified - } from "./helpers/createInstances"; - +} from "./helpers/createInstances"; // Import contract ABIs const CappedSTO = artifacts.require("./CappedSTO.sol"); @@ -18,10 +17,10 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("Concurrent STO", accounts => { +contract("Concurrent STO", async (accounts) => { // Accounts variable declaration let account_polymath; let account_issuer; @@ -57,8 +56,8 @@ contract("Concurrent STO", accounts => { let message = "Transaction Should Fail!"; // Initial fees - const initRegFee = web3.utils.toWei("250"); - const STOSetupCost = 200 * Math.pow(10, 18); + const initRegFee = new BN(web3.utils.toWei("250")); + const STOSetupCost = web3.utils.toHex(200 * Math.pow(10, 18)); // Module keys const transferManagerKey = 2; @@ -70,8 +69,12 @@ contract("Concurrent STO", accounts => { const DummySTOParameters = ["uint256", "uint256", "uint256", "string"]; const PresaleSTOParameters = ["uint256"]; + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; account_fundsReceiver = accounts[2]; @@ -139,13 +142,13 @@ contract("Concurrent STO", accounts => { 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[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey); @@ -154,12 +157,12 @@ contract("Concurrent STO", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should whitelist account_investor1", async () => { - let fromTime = latestTime(); - let toTime = latestTime() + duration.days(15); + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(15); let expiryTime = toTime + duration.days(100); let canBuyFromSTO = true; @@ -175,10 +178,10 @@ contract("Concurrent STO", accounts => { 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 = web3.utils.toWei("1000"); + const startTime = await latestTime() + duration.days(1); + const endTime = await latestTime() + duration.days(90); + const cap = new BN(web3.utils.toWei("10000")); + const rate = new BN(web3.utils.toWei("1000")); const fundRaiseType = [0]; const budget = 0; const maxCost = STOSetupCost; @@ -208,7 +211,7 @@ contract("Concurrent STO", accounts => { "CappedSTO", `Wrong STO module added at index ${STOIndex}` ); - I_STO_Array.push(CappedSTO.at(tx1.logs[3].args._module)); + I_STO_Array.push(await CappedSTO.at(tx1.logs[3].args._module)); break; case 1: // Dummy STO @@ -221,7 +224,7 @@ contract("Concurrent STO", accounts => { "DummySTO", `Wrong STO module added at index ${STOIndex}` ); - I_STO_Array.push(DummySTO.at(tx2.logs[3].args._module)); + I_STO_Array.push(await DummySTO.at(tx2.logs[3].args._module)); break; case 2: // Pre Sale STO @@ -234,7 +237,7 @@ contract("Concurrent STO", accounts => { "PreSaleSTO", `Wrong STO module added at index ${STOIndex}` ); - I_STO_Array.push(PreSaleSTO.at(tx3.logs[3].args._module)); + I_STO_Array.push(await PreSaleSTO.at(tx3.logs[3].args._module)); break; } } @@ -249,30 +252,34 @@ contract("Concurrent STO", accounts => { // Capped STO ETH await I_STO_Array[STOIndex].buyTokens(account_investor1, { from: account_investor1, - value: web3.utils.toWei("1", "ether") + value: new BN(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 }); + await I_STO_Array[STOIndex].generateTokens(account_investor1, new BN(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(), + (await I_STO_Array[STOIndex].investors.call(account_investor1)) + .div(new BN(10).pow(new BN(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, { + await I_STO_Array[STOIndex].allocateTokens(account_investor1, new BN(web3.utils.toWei("1000")), new BN(web3.utils.toWei("1")), new BN(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(), + (await I_STO_Array[STOIndex].investors.call(account_investor1)) + .div(new BN(10).pow(new BN(18))) + .toNumber(), 1000 ); break; diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index ca99abaa8..b1fe49cf8 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -1,6 +1,6 @@ const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; import latestTime from "./helpers/latestTime"; import { duration } from "./helpers/utils"; @@ -18,7 +18,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); -contract("Upgrade from v1.3.0 to v1.4.0", accounts => { +contract("Upgrade from v1.3.0 to v1.4.0", async (accounts) => { // Accounts Variable declaration let POLYMATH; let ISSUER1; @@ -31,9 +31,10 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { let tx; // Initial fee for ticker registry and security token registry - const REGFEE = web3.utils.toWei("250"); + const REGFEE = new BN(web3.utils.toWei("250")); const STOSetupCost = 0; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // Module key const STOKEY = 3; @@ -90,14 +91,16 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; // Prepare polymath network status + let currentTime; + before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); POLYMATH = accounts[0]; ISSUER1 = accounts[1]; ISSUER2 = accounts[2]; ISSUER3 = accounts[3]; MULTISIG = accounts[4]; - + I_DaiToken = await PolyTokenFaucet.new({ from: POLYMATH }); // ----------- POLYMATH NETWORK Configuration ------------ @@ -154,13 +157,13 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { 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[2].args._ticker, symbol1, "SecurityToken doesn't get deployed"); - I_SecurityToken1 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken1 = await SecurityToken.at(tx.logs[2].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[2].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - I_SecurityToken2 = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken2 = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); // Printing all the contract addresses console.log(` @@ -186,30 +189,17 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { // 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") }); + I_POLYOracle = await PolyOracle.new({ from: POLYMATH, value: new BN(web3.utils.toWei("1")) }); console.log(I_POLYOracle.address); - assert.notEqual( - I_POLYOracle.address.valueOf(), - address_zero, - "POLYOracle contract was not deployed" - ); + assert.notEqual(I_POLYOracle.address.valueOf(), address_zero, "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", - address_zero, - "ETH", - { from: POLYMATH } - ); - assert.notEqual( - I_USDOracle.address.valueOf(), - address_zero, - "USDOracle contract was not deployed" - ); + I_USDOracle = await ETHOracle.new("0x216d678c14be600cb88338e763bb57755ca2b1cf", address_zero, "ETH", { from: POLYMATH }); + assert.notEqual(I_USDOracle.address.valueOf(), address_zero, "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); @@ -220,18 +210,10 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { // Step 1: Deploy USDTieredSTOFactory\ it("Should successfully deploy USDTieredSTOFactory", async () => { I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new( - STOSetupCost, - 0, - 0, - I_USDTieredSTOProxyFactory.address, - { from: POLYMATH } - ); - assert.notEqual( - I_USDTieredSTOFactory.address.valueOf(), - address_zero, - "USDTieredSTOFactory contract was not deployed" - ); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(STOSetupCost, new BN(0), new BN(0), I_USDTieredSTOProxyFactory.address, { + from: POLYMATH + }); + assert.notEqual(I_USDTieredSTOFactory.address.valueOf(), address_zero, "USDTieredSTOFactory contract was not deployed"); let setupCost = await I_USDTieredSTOFactory.setupCost({ from: POLYMATH }); assert.equal(setupCost, STOSetupCost); }); @@ -248,12 +230,8 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { describe("CappedSTOFactory deploy", async () => { // Step 1: Deploy new CappedSTOFactory it("Should successfully deploy CappedSTOFactory", async () => { - I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(STOSetupCost, 0, 0, { from: POLYMATH }); - assert.notEqual( - I_UpgradedCappedSTOFactory.address.valueOf(), - address_zero, - "CappedSTOFactory contract was not deployed" - ); + I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(STOSetupCost, new BN(0), new BN(0), { from: POLYMATH }); + assert.notEqual(I_UpgradedCappedSTOFactory.address.valueOf(), address_zero, "CappedSTOFactory contract was not deployed"); let setupCost = await I_UpgradedCappedSTOFactory.setupCost({ from: POLYMATH }); assert.equal(setupCost, STOSetupCost); }); @@ -278,7 +256,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { describe("ManualApprovalTransferManagerFactory deploy", async () => { // Step 1: Deploy new ManualApprovalTransferManager it("Should successfully deploy ManualApprovalTransferManagerFactory", async () => { - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(0, 0, 0, { + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(0, new BN(0), new BN(0), { from: POLYMATH }); assert.notEqual( @@ -348,14 +326,14 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { 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 _startTime = await 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 = new BigNumber(100).mul(10 ** 18); - let _minimumInvestmentUSD = new BigNumber(5).mul(10 ** 18); + let _ratePerTier = [BN(0.1).mul(10 ** 18), BN(0.15).mul(10 ** 18), BN(0.2).mul(10 ** 18)]; + let _ratePerTierDiscountPoly = [BN(0), BN(0), BN(0)]; + let _tokensPerTierTotal = [BN(100).mul(10 ** 18), BN(200).mul(10 ** 18), BN(300).mul(10 ** 18)]; + let _tokensPerTierDiscountPoly = [BN(0), BN(0), BN(0)]; + let _nonAccreditedLimitUSD = new BN(100).mul(10 ** 18); + let _minimumInvestmentUSD = new BN(5).mul(10 ** 18); let _fundRaiseTypes = [0, 1]; let _wallet = ISSUER1; let _reserveWallet = ISSUER1; @@ -433,10 +411,10 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER1 }); + let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(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); + I_USDTieredSTO = await USDTieredSTO.at(tx.logs[2].args._module); }); /* @@ -445,36 +423,36 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { 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); + I_SecurityToken3 = await 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 startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - let cap = web3.utils.toWei("500000"); + let cap = new BN(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 }); + let tx = await I_SecurityToken2.addModule(I_UpgradedCappedSTOFactory.address, bytesSTO, new BN(0), new BN(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 }); + const tx = await I_SecurityToken2.addModule(I_ManualApprovalTransferManagerFactory.address, "0x0", new BN(0), new BN(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); + I_ManualApprovalTransferManagerFactory = await 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 ab796edf3..bd4161b2f 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -12,10 +12,10 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const STRGetter = artifacts.require("./STRGetter.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("SecurityTokenRegistryProxy", accounts => { +contract("SecurityTokenRegistryProxy", async (accounts) => { let I_SecurityTokenRegistry; let I_SecurityTokenRegistryProxy; let I_GeneralTransferManagerFactory; @@ -38,7 +38,7 @@ contract("SecurityTokenRegistryProxy", accounts => { let account_polymath_new; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); const version = "1.0.0"; const message = "Transaction Should Fail!"; @@ -49,6 +49,9 @@ contract("SecurityTokenRegistryProxy", accounts => { const decimals = 18; const transferManagerKey = 2; + + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; async function readStorage(contractAddress, slot) { @@ -83,7 +86,7 @@ contract("SecurityTokenRegistryProxy", accounts => { 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: --------------------- @@ -104,6 +107,7 @@ contract("SecurityTokenRegistryProxy", accounts => { // __upgradeabilityOwner -- index 13 it("Should attach the implementation and version", async () => { + I_STRGetter = await STRGetter.new({from: account_polymath}); let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, I_STFactory.address, @@ -115,8 +119,8 @@ contract("SecurityTokenRegistryProxy", accounts => { 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); + let c = await OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); + assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address.toLowerCase()); assert.equal( web3.utils .toAscii(await readStorage(c.address, 11)) @@ -125,6 +129,7 @@ contract("SecurityTokenRegistryProxy", accounts => { "1.0.0" ); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + I_STRGetter = await STRGetter.at(I_SecurityTokenRegistryProxy.address); }); it("Verify the initialize data", async () => { @@ -134,7 +139,7 @@ contract("SecurityTokenRegistryProxy", accounts => { "Should equal to 60 days" ); assert.equal( - (await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), + await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee")), web3.utils.toWei("250") ); }); @@ -142,7 +147,7 @@ contract("SecurityTokenRegistryProxy", accounts => { 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.getTokens(new BN(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"); @@ -151,15 +156,15 @@ contract("SecurityTokenRegistryProxy", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey); @@ -179,7 +184,7 @@ contract("SecurityTokenRegistryProxy", accounts => { it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async () => { await catchRevert( - I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", { from: account_polymath }) + I_SecurityTokenRegistryProxy.upgradeTo("1.1.0", address_zero, { from: account_polymath }) ); }); @@ -199,7 +204,7 @@ contract("SecurityTokenRegistryProxy", accounts => { 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); + let c = await OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); assert.equal( web3.utils .toAscii(await readStorage(c.address, 11)) @@ -208,7 +213,7 @@ contract("SecurityTokenRegistryProxy", accounts => { "1.1.0", "Version mis-match" ); - assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address, "Implemnted address is not matched"); + assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistryMock.address.toLowerCase(), "Implemnted address is not matched"); I_STRProxied = await SecurityTokenRegistryMock.at(I_SecurityTokenRegistryProxy.address); I_Getter = await STRGetter.at(I_SecurityTokenRegistryProxy.address); }); @@ -238,7 +243,7 @@ contract("SecurityTokenRegistryProxy", accounts => { it("Should change the ownership of the contract -- new address should not be 0x", async () => { await catchRevert( - I_SecurityTokenRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", { from: account_polymath }) + I_SecurityTokenRegistryProxy.transferProxyOwnership(address_zero, { from: account_polymath }) ); }); @@ -251,7 +256,7 @@ contract("SecurityTokenRegistryProxy", accounts => { 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); + let c = await OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); assert.equal( web3.utils .toAscii(await readStorage(c.address, 11)) @@ -260,16 +265,19 @@ contract("SecurityTokenRegistryProxy", accounts => { "1.2.0", "Version mis-match" ); - assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address, "Implemnted address is not matched"); + assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address.toLowerCase(), "Implemnted address is not matched"); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); }); - it("Should get the version", async() => { + it("Should get the version", async () => { assert.equal(await I_SecurityTokenRegistryProxy.version.call({ from: account_polymath_new }), "1.2.0"); }); - it("Should get the implementation address", async() => { - assert.equal(await I_SecurityTokenRegistryProxy.implementation.call({ from: account_polymath_new }), I_SecurityTokenRegistry.address); - }) + it("Should get the implementation address", async () => { + assert.equal( + await I_SecurityTokenRegistryProxy.implementation.call({ from: account_polymath_new }), + I_SecurityTokenRegistry.address + ); + }); }); }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 88a22af93..19ddab75b 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -15,10 +15,10 @@ const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionMa const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("ModuleRegistryProxy", accounts => { +contract("ModuleRegistryProxy", async (accounts) => { let I_SecurityTokenRegistry; let I_SecurityTokenRegistryProxy; let I_GeneralTransferManagerFactory; @@ -42,10 +42,11 @@ contract("ModuleRegistryProxy", accounts => { let account_polymath_new; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); const version = "1.0.0"; const message = "Transaction Should Fail!"; const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; // SecurityToken Details for funds raise Type ETH const name = "Team"; const symbol = "SAP"; @@ -111,8 +112,8 @@ contract("ModuleRegistryProxy", accounts => { it("Should attach the MR implementation and version", async () => { let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); await I_ModuleRegistryProxy.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); + let c = await OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address.toLowerCase()); assert.equal( web3.utils .toAscii(await readStorage(c.address, 11)) @@ -127,9 +128,13 @@ 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 }); + let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new( + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + { from: account_polymath } + ); - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, 0, 0, I_GeneralTransferManagerLogic.address, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { from: account_polymath }); @@ -148,11 +153,7 @@ contract("ModuleRegistryProxy", accounts => { // Step 3: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - assert.notEqual( - I_STFactory.address.valueOf(), - address_zero, - "STFactory contract was not deployed" - ); + assert.notEqual(I_STFactory.address.valueOf(), address_zero, "STFactory contract was not deployed"); }); it("Verify the initialize data", async () => { @@ -168,7 +169,7 @@ contract("ModuleRegistryProxy", accounts => { describe("Feed some data in storage", async () => { it("Register and verify the new module", async () => { I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(0, 0, 0, I_GeneralPermissionManagerLogic.address, { + I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(0, new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, { from: account_polymath }); @@ -195,7 +196,7 @@ contract("ModuleRegistryProxy", accounts => { it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async () => { await catchRevert( - I_ModuleRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", { from: account_polymath }) + I_ModuleRegistryProxy.upgradeTo("1.1.0", address_zero, { from: account_polymath }) ); }); @@ -213,7 +214,7 @@ contract("ModuleRegistryProxy", accounts => { 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); + let c = await OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); assert.equal( web3.utils .toAscii(await readStorage(c.address, 11)) @@ -222,7 +223,7 @@ contract("ModuleRegistryProxy", accounts => { "1.1.0", "Version mis-match" ); - assert.equal(await readStorage(c.address, 12), I_MockModuleRegistry.address, "Implemnted address is not matched"); + assert.equal(await readStorage(c.address, 12), I_MockModuleRegistry.address.toLowerCase(), "Implemnted address is not matched"); I_MRProxied = await MockModuleRegistry.at(I_ModuleRegistryProxy.address); }); }); @@ -230,7 +231,7 @@ contract("ModuleRegistryProxy", accounts => { 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"); + assert.equal(_data.length, new BN(0), "Should give the original length"); }); it("Should alter the old storage", async () => { @@ -249,7 +250,7 @@ contract("ModuleRegistryProxy", accounts => { it("Should change the ownership of the contract -- new address should not be 0x", async () => { await catchRevert( - I_ModuleRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", { from: account_polymath }) + I_ModuleRegistryProxy.transferProxyOwnership(address_zero, { from: account_polymath }) ); }); @@ -262,7 +263,7 @@ contract("ModuleRegistryProxy", accounts => { 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); + let c = await OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); assert.equal( web3.utils .toAscii(await readStorage(c.address, 11)) @@ -271,7 +272,7 @@ contract("ModuleRegistryProxy", accounts => { "1.2.0", "Version mis-match" ); - assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address, "Implemnted address is not matched"); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address.toLowerCase(), "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 5059388a0..28ccaded7 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -1,9 +1,8 @@ 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 { catchRevert } from "./helpers/exceptions"; -import { setUpPolymathNetwork, deployRedemptionAndVerifyed } from "./helpers/createInstances"; +import {duration, promisifyLogWatch} from "./helpers/utils"; +import takeSnapshot, {increaseTime, revertToSnapshot} from "./helpers/time"; +import {catchRevert} from "./helpers/exceptions"; +import {deployRedemptionAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); @@ -11,10 +10,10 @@ const TrackedRedemption = artifacts.require("./TrackedRedemption"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const Web3 = require("web3"); -const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("TrackedRedemption", accounts => { +contract("TrackedRedemption", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -25,11 +24,6 @@ contract("TrackedRedemption", accounts => { 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 @@ -69,10 +63,14 @@ contract("TrackedRedemption", accounts => { const burnKey = 5; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); + + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -107,7 +105,7 @@ contract("TrackedRedemption", accounts => { // STEP 4: Deploy the TrackedRedemption [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, 0); - [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, new BN(web3.utils.toWei("500"))); // Printing all the contract addresses console.log(` @@ -137,15 +135,15 @@ contract("TrackedRedemption", 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -154,32 +152,34 @@ contract("TrackedRedemption", accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should successfully attach the paid TrackedRedemption with the security token", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(P_TrackedRedemptionFactory.address, "", web3.utils.toWei("500"), 0, { from: token_owner }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_TrackedRedemptionFactory.address, "0x0", new BN(web3.utils.toWei("500")), new BN(0), { + from: token_owner + }); assert.equal(tx.logs[3].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), "TrackedRedemption", "TrackedRedemption module was not added" ); - I_TrackedRedemption = TrackedRedemption.at(tx.logs[3].args._module); + I_TrackedRedemption = await TrackedRedemption.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); 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 }); + const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "0x0", new BN(0), new BN(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); + I_TrackedRedemption = await TrackedRedemption.at(tx.logs[2].args._module); }); }); @@ -189,9 +189,9 @@ contract("TrackedRedemption", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(30), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(30))), true, { from: account_issuer, @@ -209,9 +209,9 @@ contract("TrackedRedemption", 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Buy some tokens for account_investor2 (2 ETH)", async () => { @@ -219,9 +219,9 @@ contract("TrackedRedemption", accounts => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(30), + currentTime, + currentTime, + currentTime.add(new BN(duration.days(30))), true, { from: account_issuer, @@ -236,23 +236,23 @@ contract("TrackedRedemption", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("2", "ether"), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); it("Redeem some tokens - fail insufficient allowance", async () => { await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, { from: token_owner }); - await catchRevert(I_TrackedRedemption.redeemTokens(web3.utils.toWei("1", "ether"), { from: account_investor1 })); + await catchRevert(I_TrackedRedemption.redeemTokens(new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); }); 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 }); + await I_SecurityToken.approve(I_TrackedRedemption.address, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + let tx = await I_TrackedRedemption.redeemTokens(new BN(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"); + assert.equal(web3.utils.fromWei(web3.utils.toBN(tx.logs[0].args._value)), 1, "Wrong value"); }); it("Get the init data", async () => { diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 00419b1d8..5b2a4f8e8 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -1,21 +1,20 @@ -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 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 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 => { +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port +contract("LockupVolumeRestrictionTransferManager", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -25,11 +24,6 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { 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 @@ -66,10 +60,14 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); - before(async() => { - // Accounts setup + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; + + before(async () => { + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -99,7 +97,11 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { // STEP 4(c): Deploy the VolumeRestrictionTransferManager [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, 0); // STEP 4(d): Deploy the VolumeRestrictionTransferManager - [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified( + account_polymath, + I_MRProxied, + new BN(web3.utils.toWei("500")) + ); // Printing all the contract addresses console.log(` @@ -120,288 +122,291 @@ 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()); }); 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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // 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" - ); + 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); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = await 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() => { + 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), + currentTime, + currentTime, + currentTime.add(new BN(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"); + 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 }); + await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('2', 'ether') - ); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); - 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( account_investor2, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(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"); + 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 }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor2)).toNumber(), - web3.utils.toWei('10', 'ether') - ); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); 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 I_PolyToken.getTokens(new BN(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, new BN(0), new BN(web3.utils.toWei("500", "ether")), new BN(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"); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + const tx = await I_SecurityToken.addModule( + P_VolumeRestrictionTransferManagerFactory.address, + new BN(0), + new BN(web3.utils.toWei("500", "ether")), + new BN(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, ''), + 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); + P_VolumeRestrictionTransferManager = await 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 }); + const tx = await I_SecurityToken.addModule(I_VolumeRestrictionTransferManagerFactory.address, new BN(0), new BN(0), new BN(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, ''), + 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); + I_VolumeRestrictionTransferManager = await 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, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(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"); + 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 }); + await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor3)).toNumber(), - web3.utils.toWei('10', 'ether') - ); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); - 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('3', 'ether') - ); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("3", "ether")).toString()); }); - 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( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, 0, 0, { from: token_owner }) - ) + await catchRevert(I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, new BN(0), new BN(0), { from: token_owner })); }); - 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( - I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 0, 0, web3.utils.toWei('1', 'ether'), { from: token_owner }) + I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, new BN(0), new BN(0), new BN(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() => { + 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 }) + I_VolumeRestrictionTransferManager.addLockUp(account_investor2, new BN(0), 4, new BN(0), new BN(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() => { + 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 }) + I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, new BN(0), new BN(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() => { - + 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 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 }) - ); + await catchRevert(I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 17, 4, new BN(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() => { - + 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_VolumeRestrictionTransferManager.addLockUp( + account_investor2, + new BN(web3.utils.toWei("16", "ether")), + 4, + new BN(0), + new BN(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() => { - + 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 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 }) - ); - + await catchRevert(I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 16, 4, new BN(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()); + it("Should prevent the transfer of tokens in a lockup", async () => { + let balance = await I_SecurityToken.balanceOf(account_investor2); + console.log("balance", balance.div(new BN(1).mul(new BN(10).pow(new BN(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 }); + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, new BN(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) + let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call( + account_investor2, + account_investor1, + new BN(web3.utils.toWei("1", "ether")), + new BN(0), + false + ); // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '0') + assert.equal(result.toString(), "0"); - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); }); - 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)); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + await I_SecurityToken.transfer(account_investor1, new BN(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 prevent the transfer of tokens if the amount is larger than the amount allowed by lockups", async () => { + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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); - await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); + await I_SecurityToken.transfer(account_investor1, new BN(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) + 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); @@ -409,118 +414,101 @@ 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) - let balance = await I_SecurityToken.balanceOf(account_investor1) + 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 }); + await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, new BN(0), balance, { from: token_owner }); // let blockNumber = await web3.eth.getBlockNumber(); // console.log('blockNumber',blockNumber) - let now = (await web3.eth.getBlock('latest')).timestamp + let now = (await web3.eth.getBlock("latest")).timestamp; - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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) + 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[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 }); + await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, new BN(0), 8, 4, new BN(0), balance, { from: token_owner }); // attempt a transfer - await catchRevert( - I_SecurityToken.transfer(account_investor2, web3.utils.toWei('6', 'ether'), { from: account_investor1 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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 }); - + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("6", "ether")), { from: account_investor1 }); }); - it("Should succesfully modify the lockup - fail because array index out of bound", async() => { + 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 }) + I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 8, 8, 4, new BN(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() => { + it("Should succesfully get the lockup - fail because array index out of bound", async () => { + await catchRevert(I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 9)); + }); - let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) + 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 }) - ); + 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) + assert.equal(lockUpCount, 1); // remove the lockup - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, 0, { from: token_owner }); + await I_VolumeRestrictionTransferManager.removeLockUp(account_investor1, new BN(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) + 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 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 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 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 })); + }); - let balancesBefore = {} + 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) - + balancesBefore[account_investor2] = await I_SecurityToken.balanceOf(account_investor2); // should be 10000000000000000000 - balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3) - + balancesBefore[account_investor3] = await I_SecurityToken.balanceOf(account_investor3); - let lockUpCountsBefore = {} + 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 + 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) + assert.equal(lockUpCountsBefore[account_investor3], 0); // create lockups for their entire balances await I_VolumeRestrictionTransferManager.addLockUpMulti( @@ -532,22 +520,18 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { { 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, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor3 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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()) + 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()) + 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); @@ -561,250 +545,249 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("5", "ether")), { from: account_investor3 }); + balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2); + assert.equal( + balancesBefore[account_investor2].sub(new BN(web3.utils.toWei("2", "ether"))).toString(), + balancesAfter[account_investor2].toString() + ); - 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()) - + balancesAfter[account_investor3] = await I_SecurityToken.balanceOf(account_investor3); + assert.equal( + balancesBefore[account_investor3].sub(new BN(web3.utils.toWei("5", "ether"))).toString(), + balancesAfter[account_investor3].toString() + ); }); - 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], + [new BN(web3.utils.toWei("1", "ether")), new BN(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); assert.equal(lockUpsLength, 2); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 0, { from: token_owner }); + await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, new BN(0), { from: token_owner }); + await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, new BN(0), { from: token_owner }); lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); assert.equal(lockUpsLength, 0); - let now = latestTime(); + let now = await latestTime(); // balance here should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) + let balance = await I_SecurityToken.balanceOf(account_investor2); - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + duration.seconds(4), balance, { from: token_owner }); + 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 }) - ); - + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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() => { - + it("Should be possible to edit a lockup with a specific start time in the future", async () => { // edit the lockup - let now = latestTime(); + let now = await latestTime(); // should be 10000000000000000000 - let balance = await I_SecurityToken.balanceOf(account_investor2) + 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) + 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.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 }); + await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, new BN(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) + 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.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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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 }); - + await I_SecurityToken.transfer(account_investor1, new BN(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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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) + let result = await I_VolumeRestrictionTransferManager.verifyTransfer.call( + account_investor2, + account_investor1, + new BN(web3.utils.toWei("5", "ether")), + new BN(0), + false + ); // enum Result {INVALID, NA, VALID, FORCE_VALID} and we want VALID so it should be 2 - assert.equal(result.toString(), '2') + assert.equal(result.toString(), "2"); let lockUpAfterVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); - assert.equal(lockUpBeforeVerify[4].toString(), lockUpAfterVerify[4].toString()) + 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 }); + await I_SecurityToken.transfer(account_investor1, new BN(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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); }); - 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) + 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) + assert.equal(lockUpCount.toString(), 0); - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, 0, web3.utils.toWei('6', 'ether'), { from: token_owner }); + await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 12, 4, new BN(0), new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor1, new BN(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 }); + await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, new BN(0), new BN(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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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 }) - ); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(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 }); + await I_SecurityToken.transfer(account_investor1, new BN(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 }); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - balance = await I_SecurityToken.balanceOf(account_investor1) - assert.equal(balance.toString(), web3.utils.toWei('2', 'ether')) + balance = await I_SecurityToken.balanceOf(account_investor1); + assert.equal(balance.toString(), new BN(web3.utils.toWei("2", "ether"))); }); - - 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, '')) - assert.equal(web3.utils.toAscii(perm[0]).replace(/\u0000/g, ''), "ADMIN") + 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"); + 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() => { + 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"); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Volume"); }); }); - }); diff --git a/test/y_scheduled_checkpoints.js b/test/y_scheduled_checkpoints.js index 4829eec5f..aa490f32e 100644 --- a/test/y_scheduled_checkpoints.js +++ b/test/y_scheduled_checkpoints.js @@ -1,20 +1,18 @@ -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 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 SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const ScheduledCheckpoint = artifacts.require("./ScheduledCheckpoint.sol"); +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -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 => { - +contract("ScheduledCheckpoint", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -24,11 +22,6 @@ contract('ScheduledCheckpoint', accounts => { 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 @@ -63,10 +56,14 @@ contract('ScheduledCheckpoint', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); - before(async() => { - // Accounts setup + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; + + before(async () => { + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -115,264 +112,274 @@ contract('ScheduledCheckpoint', 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()); }); 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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // 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" - ); + 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); - + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); - }); - describe("Buy tokens using on-chain whitelist", async() => { - + 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 }); + await I_SecurityToken.changeGranularity(1, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_ScheduledCheckpointFactory.address, "0x0", new BN(0), new BN(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, ''), + 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); + I_ScheduledCheckpoint = await ScheduledCheckpoint.at(tx.logs[2].args._module); }); let startTime; let interval; it("Should create a daily checkpoint", async () => { - startTime = latestTime() + 100; + startTime = await 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()); + await I_ScheduledCheckpoint.addSchedule(web3.utils.fromAscii("CP1"), startTime, interval, { from: token_owner }); + console.log("2: " + await latestTime()); }); it("Remove (temp) daily checkpoint", async () => { let snap_Id = await takeSnapshot(); - await I_ScheduledCheckpoint.removeSchedule("CP1", {from: token_owner}); + await I_ScheduledCheckpoint.removeSchedule(web3.utils.fromAscii("CP1"), { from: token_owner }); await revertToSnapshot(snap_Id); }); - it("Should Buy the tokens for account_investor1", async() => { + it("Should Buy the tokens for account_investor1", async () => { // Add the Investor in to the whitelist - console.log("3: " + latestTime()); + console.log("3: " + await latestTime()); let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor1, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(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"); + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); // Jump time - console.log("4: " + latestTime()); + console.log("4: " + await latestTime()); await increaseTime(5000); // We should be after the first scheduled checkpoint, and before the second - console.log("5: " + latestTime()); + console.log("5: " + await latestTime()); - assert.isTrue(latestTime() > startTime); - assert.isTrue(latestTime() <= startTime + interval); - console.log("6: " + latestTime()); + assert.isTrue(await latestTime() > startTime); + assert.isTrue(await latestTime() <= startTime + interval); + console.log("6: " + await latestTime()); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('1', 'ether'), { from: token_owner }); + await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal( - (await I_SecurityToken.balanceOf(account_investor1)).toNumber(), - web3.utils.toWei('1', 'ether') - ); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); - it("Should have checkpoint created with correct balances", async() => { - let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + it("Should have checkpoint created with correct balances", async () => { + let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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() => { + 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), + currentTime, + currentTime, + currentTime.add(new BN(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"); + 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); + assert.isTrue(await latestTime() > startTime); + assert.isTrue(await latestTime() <= startTime + interval); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei('1', 'ether'), { from: token_owner }); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); - it("No additional checkpoints created", async() => { - let cp1 = await I_ScheduledCheckpoint.getSchedule("CP1"); + it("No additional checkpoints created", async () => { + let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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() => { - + it("Add a new token holder - account_investor3", async () => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, - latestTime(), - latestTime(), - latestTime() + duration.days(10), + currentTime, + currentTime, + currentTime.add(new BN(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"); + 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)); + assert.isTrue(await latestTime() > startTime + interval); + assert.isTrue(await 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 }); + await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("1", "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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); - 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]); + it("Should have new checkpoint created with correct balances", async () => { + let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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_investor2, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); 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, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); - it("Should have correct balances for investor 3 after new checkpoint", async() => { + 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.isTrue(await latestTime() > startTime + 3 * interval); + assert.isTrue(await latestTime() <= startTime + 4 * interval); + await I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("0.5", "ether")), { from: account_investor1 }); + let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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_investor3, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); 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, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); 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, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); - it("Manually update checkpoints", async() => { + 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]); + await I_ScheduledCheckpoint.updateAll({ from: token_owner }); + + let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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_investor3, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 4)).toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); 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_investor2, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 4)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); 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')); - + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 4)).toString(), new BN(web3.utils.toWei("0.5", "ether")).toString()); }); - it("Should get the permission", async() => { + 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(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); diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 6bff3ee24..2614e6d5d 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -1,32 +1,32 @@ -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 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 +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 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 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 Fuzz', accounts => { +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port +contract("GeneralPermissionManager Fuzz", async (accounts) => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -38,10 +38,6 @@ contract('GeneralPermissionManager Fuzz', accounts => { 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!"; @@ -85,7 +81,7 @@ contract('GeneralPermissionManager Fuzz', accounts => { const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; - const delegateDetails = "Hello I am legit delegate"; + const managerDetails = web3.utils.fromAscii("Hello"); const STVRParameters = ["bool", "uint256", "bool"]; // Module key @@ -94,21 +90,25 @@ contract('GeneralPermissionManager Fuzz', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = new BN(web3.utils.toWei("250")); // CountTransferManager details - const holderCount = 2; // Maximum number of token holders - let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); + const holderCount = 2; // Maximum number of token holders + let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); - let _details = "details holding for test"; + let _details = "details holding for test"; let testRepeat = 20; - // permission manager fuzz test - let perms = ['ADMIN','WHITELIST', 'FLAGS', 'TRANSFER_APPROVAL']; - let totalPerms = perms.length; + // permission manager fuzz test + let perms = ["ADMIN", "WHITELIST", "FLAGS", "TRANSFER_APPROVAL"]; + let totalPerms = perms.length; + + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + const one_address = "0x0000000000000000000000000000000000000001"; before(async () => { - // Accounts setup + currentTime = new BN(await latestTime()); account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -122,7 +122,6 @@ contract('GeneralPermissionManager Fuzz', accounts => { account_delegate = accounts[7]; // account_delegate2 = accounts[6]; - // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -144,9 +143,9 @@ contract('GeneralPermissionManager Fuzz', accounts => { // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 6: Deploy the GeneralDelegateManagerFactory - [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, new BN(web3.utils.toWei("500"))); - // Deploy Modules + // Deploy Modules [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, 0); @@ -182,15 +181,15 @@ contract('GeneralPermissionManager Fuzz', 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 }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - I_SecurityToken = SecurityToken.at(tx.logs[2].args._securityTokenAddress); + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -199,25 +198,27 @@ contract('GeneralPermissionManager Fuzz', accounts => { it("Should intialize the auto attached modules", async () => { let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + I_GeneralTransferManager = await 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 I_PolyToken.getTokens(new BN(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 }) + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + from: token_owner + }) ); }); it("Should successfully attach the General permission manager factory with the security token - paid module", 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, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_GeneralPermissionManagerFactory.address, "0x", - web3.utils.toWei("500", "ether"), - 0, + new BN(web3.utils.toWei("500", "ether")), + new BN(0), { from: token_owner } ); assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); @@ -226,204 +227,285 @@ contract('GeneralPermissionManager Fuzz', accounts => { "GeneralPermissionManager", "GeneralPermissionManagerFactory module was not added" ); - P_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[3].args._module); + P_GeneralPermissionManager = await GeneralPermissionManager.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); it("Should successfully attach the General permission manager factory with the security token - free module", async () => { - const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", new BN(0), new BN(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); + I_GeneralPermissionManager = await 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 + 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 }); + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ((await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"))) === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), false, { + from: token_owner + }); + } else if ( + (await I_GeneralPermissionManager.checkPermission(accounts[j], I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))) === true + ) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, web3.utils.fromAscii("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 fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); - await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, randomPerms, true, { from: token_owner }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_GeneralTransferManager.address, web3.utils.fromAscii(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 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] }); + 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] }); + 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] }); + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(!currentAllowAllWhitelistTransfersStats, { + from: accounts[j] + }); assert.equal(await I_GeneralTransferManager.allowAllWhitelistTransfers(), !currentAllowAllWhitelistTransfersStats); - await I_GeneralTransferManager.changeAllowAllWhitelistIssuances(!currentAllowAllWhitelistIssuancesStats, { from: accounts[j] }); + 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") + 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"); + 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] }); + 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] }); + 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] })); + 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] })); + 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 }); + 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, new BN(0), new BN(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); + I_CountTransferManager = await 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 + 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 }); - } + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ((await I_GeneralPermissionManager.checkPermission(accounts[j], I_CountTransferManager.address, web3.utils.fromAscii("ADMIN"))) === true) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, web3.utils.fromAscii("ADMIN"), false, { + from: token_owner + }); } - // assign a random perm + // 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') { + await I_GeneralPermissionManager.changePermission(accounts[j], I_CountTransferManager.address, web3.utils.fromAscii(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 { + 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"); - } - } + 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 () => { + 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); + const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner }); + I_PercentageTransferManager = await 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 + 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 }); + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ( + (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii("WHITELIST"))) === + true + ) { + await I_GeneralPermissionManager.changePermission( + accounts[j], + I_PercentageTransferManager.address, + web3.utils.fromAscii("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 }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii(randomPerms), true, { + from: token_owner + }); //try add multi lock ups - if (randomPerms === 'WHITELIST') { + 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"); @@ -437,70 +519,93 @@ contract('GeneralPermissionManager Fuzz', accounts => { 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++) { + 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 + 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 }); + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ( + (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii("WHITELIST"))) === + true + ) { + await I_GeneralPermissionManager.changePermission( + accounts[j], + I_PercentageTransferManager.address, + web3.utils.fromAscii("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 }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii(randomPerms), true, { + from: token_owner + }); - if (randomPerms === 'WHITELIST') { + 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"); - + 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] })); + 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(); + // 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++) { - + 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 + 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 }); + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ( + (await I_GeneralPermissionManager.checkPermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii("ADMIN"))) === true + ) { + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii("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 }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_PercentageTransferManager.address, web3.utils.fromAscii(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"); - + 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] })); + 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); @@ -508,53 +613,65 @@ contract('GeneralPermissionManager Fuzz', accounts => { }); }); - 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 }); + const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "0x0", new BN(0), new BN(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); + I_ManualApprovalTransferManager = await 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 + 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 }); + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ( + (await I_GeneralPermissionManager.checkPermission( + accounts[j], + I_ManualApprovalTransferManager.address, + web3.utils.fromAscii("TRANSFER_APPROVAL") + )) === true + ) { + await I_GeneralPermissionManager.changePermission( + accounts[j], + I_ManualApprovalTransferManager.address, + web3.utils.fromAscii("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 }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, web3.utils.fromAscii(randomPerms), true, { + from: token_owner + }); - if (randomPerms === "TRANSFER_APPROVAL" ) { + if (randomPerms === "TRANSFER_APPROVAL") { console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); + let nextTime = await latestTime() + duration.days(1); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + new BN(web3.utils.toWei("2", "ether")), + nextTime, { from: accounts[j] } ); @@ -570,42 +687,42 @@ contract('GeneralPermissionManager Fuzz', accounts => { 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"); + let nextTime = await latestTime() + duration.days(1); await catchRevert( I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + new BN(web3.utils.toWei("2", "ether")), + nextTime, { from: accounts[j] } ) ); + nextTime = await latestTime() + duration.days(1); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - web3.utils.toWei("2", "ether"), - latestTime() + duration.days(1), + new BN(web3.utils.toWei("2", "ether")), + nextTime, { from: token_owner } ); - await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, { - from: accounts[j] - }) + 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), { + await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(duration.days(1))), { from: token_owner }); console.log("2"); @@ -614,31 +731,52 @@ contract('GeneralPermissionManager Fuzz', accounts => { // 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 + 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 }); + if ((await I_GeneralPermissionManager.checkDelegate(accounts[j])) !== true) { + await I_GeneralPermissionManager.addDelegate(accounts[j], web3.utils.fromAscii(_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 }); + if ( + (await I_GeneralPermissionManager.checkPermission( + accounts[j], + I_ManualApprovalTransferManager.address, + web3.utils.fromAscii("TRANSFER_APPROVAL") + )) === true + ) { + await I_GeneralPermissionManager.changePermission( + accounts[j], + I_ManualApprovalTransferManager.address, + web3.utils.fromAscii("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 }); + await I_GeneralPermissionManager.changePermission(accounts[j], I_ManualApprovalTransferManager.address, web3.utils.fromAscii(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] - }); + let nextTime = new BN(await latestTime()).add(new BN(duration.days(1))); + await I_ManualApprovalTransferManager.addManualBlocking( + account_investor1, + account_investor2, + nextTime, + { + from: accounts[j] + } + ); console.log("2"); await I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }); @@ -646,15 +784,27 @@ contract('GeneralPermissionManager Fuzz', accounts => { 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"); + let nextTime = new BN(await latestTime()).add(new BN(duration.days(1))); await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: accounts[j] - }) + I_ManualApprovalTransferManager.addManualBlocking( + account_investor1, + account_investor2, + nextTime, + { + from: accounts[j] + } + ) ); - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(1), { - from: token_owner - }); + nextTime = new BN(await latestTime()).add(new BN(duration.days(1))); + await I_ManualApprovalTransferManager.addManualBlocking( + account_investor1, + account_investor2, + nextTime, + { + from: token_owner + } + ); await catchRevert( I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, account_investor2, { from: accounts[j] }) @@ -664,8 +814,7 @@ contract('GeneralPermissionManager Fuzz', accounts => { } await revertToSnapshot(snapId); - }; + } }); }); - }); diff --git a/truffle-ci.js b/truffle-ci.js index f427eb332..008baa8ec 100644 --- a/truffle-ci.js +++ b/truffle-ci.js @@ -17,11 +17,16 @@ module.exports = { gasPrice: 0x01 // <-- Use this low gas price } }, - solc: { - optimizer: { - enabled: true, - runs: 200, - }, + compilers: { + solc: { + version: "native", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + } }, mocha: { enableTimeouts: false, diff --git a/truffle-config.js b/truffle-config.js index c993327ea..c6d636e97 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -53,15 +53,20 @@ module.exports = { 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 + gas: 0xfffffffff , // <-- Use this high gas value gasPrice: 0x01 // <-- Use this low gas price } }, - solc: { - optimizer: { - enabled: true, - runs: 200, - }, + compilers: { + solc: { + version: "native", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + } }, mocha: { enableTimeouts: false diff --git a/upgrade.js b/upgrade.js new file mode 100644 index 000000000..af0561dac --- /dev/null +++ b/upgrade.js @@ -0,0 +1,19 @@ +const fs = require('fs'); +const glob = require("glob"); + +let regex = new RegExp('((const|let|var) (.*) = artifacts.require(.)*)', 'gi'); +let m; + +glob("test/**/*.js", function (er, files) { + files.forEach(function(filename) { + fs.readFile(filename, 'utf-8', function(err, content) { + if (err) { + return console.log(err); + } + content = content.replace(regex, '$1\n$3.numberFormat = "BN";'); + fs.writeFile(filename, content, 'utf8', function (err) { + if (err) return console.log(err); + }); + }); + }); +}) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 74912abd4..fbe3ccc99 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,10 +19,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" @@ -40,26 +42,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" @@ -67,6 +74,7 @@ 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" @@ -77,10 +85,12 @@ acorn-jsx@^5.0.0: 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: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^6.0.2: version "6.0.4" @@ -89,18 +99,22 @@ 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@^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.3.0: +ajv@^5.1.1, 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" @@ -125,9 +139,20 @@ ajv@^6.5.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +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" + integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc= dependencies: kind-of "^3.0.2" longest "^1.0.1" @@ -136,6 +161,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" @@ -143,36 +169,49 @@ 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" @@ -180,17 +219,25 @@ 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" +app-module-path@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= + 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" @@ -198,22 +245,26 @@ 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" @@ -222,32 +273,22 @@ arr-union@^3.1.0: 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" @@ -256,30 +297,41 @@ 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= + +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" @@ -292,44 +344,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" @@ -338,6 +400,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" @@ -362,6 +425,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" @@ -375,6 +439,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" @@ -383,6 +448,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" @@ -391,6 +457,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" @@ -400,6 +467,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" @@ -409,6 +477,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" @@ -417,6 +486,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" @@ -426,6 +496,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" @@ -436,6 +507,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" @@ -443,6 +515,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" @@ -450,6 +523,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" @@ -457,6 +531,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" @@ -465,6 +540,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" @@ -475,6 +551,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" @@ -486,6 +563,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" @@ -493,50 +571,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" @@ -545,6 +634,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" @@ -553,6 +643,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" @@ -562,6 +653,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" @@ -572,18 +664,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" @@ -594,6 +689,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" @@ -608,6 +704,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" @@ -615,12 +712,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" @@ -628,12 +727,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" @@ -642,12 +743,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" @@ -656,6 +759,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" @@ -665,6 +769,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" @@ -673,6 +778,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" @@ -681,6 +787,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" @@ -688,6 +795,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" @@ -699,6 +807,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" @@ -706,12 +815,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" @@ -720,18 +831,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" @@ -740,6 +854,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" @@ -748,6 +863,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" @@ -755,12 +871,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" @@ -768,6 +886,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" @@ -776,6 +895,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" @@ -811,6 +931,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" @@ -840,6 +961,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" @@ -849,6 +971,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" @@ -859,6 +982,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" @@ -871,6 +995,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" @@ -878,6 +1003,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" @@ -888,6 +1014,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" @@ -902,6 +1029,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" @@ -911,6 +1039,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" @@ -918,28 +1047,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" @@ -952,12 +1087,14 @@ 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@5.0.0: version "5.0.0" @@ -966,10 +1103,12 @@ 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@^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" + integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== "bignumber.js@git+https://github.com/debris/bignumber.js#master": version "2.0.7" @@ -986,20 +1125,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" @@ -1008,16 +1151,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" @@ -1025,32 +1182,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" @@ -1064,10 +1228,11 @@ 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 "^6.0.0" + bignumber.js "^7.2.1" commander "^2.15.0" ieee754 "^1.1.8" json-text-sequence "^0.1" @@ -1075,6 +1240,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" @@ -1082,6 +1248,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" @@ -1090,6 +1257,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" @@ -1105,18 +1273,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" @@ -1128,6 +1300,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" @@ -1136,6 +1309,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" @@ -1145,6 +1319,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" @@ -1152,12 +1327,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" @@ -1170,12 +1347,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" @@ -1183,16 +1362,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" @@ -1201,14 +1383,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" @@ -1216,30 +1401,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" @@ -1248,6 +1440,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" @@ -1256,6 +1449,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" @@ -1263,18 +1457,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" @@ -1289,43 +1487,52 @@ 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" 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.30000921" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000921.tgz#7a607c1623444b22351d834e093aedda3c42fbe8" + integrity sha512-Bu09ciy0lMWLgpYC77I0YGuI8eFRBPPzaSOYJK1jTI64txCphYCqnWbxJYjHABYVt/TYX/p3jNjLBR87u1Bfpw== 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" @@ -1333,6 +1540,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" @@ -1343,6 +1551,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" @@ -1359,12 +1568,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" @@ -1380,6 +1591,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" @@ -1396,13 +1608,15 @@ chokidar@^2.0.2: 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" @@ -1410,19 +1624,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" @@ -1434,16 +1651,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" @@ -1452,6 +1672,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" @@ -1460,6 +1681,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" @@ -1468,18 +1690,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" @@ -1487,6 +1713,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" @@ -1494,126 +1721,146 @@ 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" -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" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 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" + version "2.6.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.0.tgz#1e30793e9ee5782b307e37ffa22da0eacddd84d4" + integrity sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw== 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" @@ -1621,6 +1868,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" @@ -1632,6 +1880,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" @@ -1639,6 +1888,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" @@ -1649,6 +1899,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" @@ -1657,16 +1908,18 @@ 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" @@ -1689,6 +1942,7 @@ crypt@~0.0.1: 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" @@ -1705,64 +1959,77 @@ 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-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@*, 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.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" @@ -1773,16 +2040,19 @@ decamelize@^1.0.0, decamelize@^1.1.1: 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" @@ -1791,6 +2061,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" @@ -1801,6 +2072,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" @@ -1809,6 +2081,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" @@ -1818,6 +2091,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" @@ -1831,52 +2105,62 @@ 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" + 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" @@ -1884,38 +2168,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" @@ -1923,28 +2201,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" @@ -1953,6 +2237,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" @@ -1960,20 +2245,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" @@ -1982,16 +2271,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" @@ -1999,25 +2291,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.92" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.92.tgz#9027b5abaea400045edd652c0e4838675c814399" + integrity sha512-En051LMzMl3/asMWGZEtU808HOoVWIpmmZx1Ep8N+TT9e7z/X8RcLeBU2kLSNLGQ+5SuKELzMx+MVuTBXk6Q9w== 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" @@ -2027,6 +2324,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" @@ -2039,6 +2337,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" @@ -2048,6 +2347,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" @@ -2057,29 +2357,39 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.1.tgz#5a132b28ebf84a289ba692862f7d4206ebcd32d0" + integrity sha512-cjx7oFbFIyZMpmWaEBnKeJXWAVzjXwK6yHiz/5X73A2Ww4pnabw+4ZaA/MxLroIQQrB3dL6XzEz8P3aZsSdj8Q== + 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" @@ -2089,28 +2399,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: +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: 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" @@ -2121,6 +2436,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" @@ -2129,6 +2445,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" @@ -2137,6 +2454,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" @@ -2145,6 +2463,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" @@ -2156,6 +2475,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" @@ -2166,6 +2486,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" @@ -2173,6 +2494,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" @@ -2182,14 +2504,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" @@ -2201,6 +2526,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" @@ -2214,6 +2540,7 @@ eslint-config-standard@^12.0.0: 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" @@ -2221,6 +2548,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" @@ -2235,6 +2563,7 @@ eslint-plugin-es@^1.3.1: 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" @@ -2280,6 +2609,7 @@ 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@^5.8.0: version "5.8.0" @@ -2324,53 +2654,70 @@ eslint@^5.8.0: table "^5.0.2" text-table "^0.2.0" -espree@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" +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" eslint-visitor-keys "^1.0.0" +esprima-extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" + integrity sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw== + dependencies: + esprima "^4.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" @@ -2384,6 +2731,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" @@ -2396,6 +2744,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" @@ -2404,6 +2753,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" @@ -2420,6 +2770,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" @@ -2427,6 +2778,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" @@ -2434,6 +2786,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" @@ -2464,14 +2817,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" @@ -2486,14 +2842,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" @@ -2501,25 +2859,40 @@ 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" + 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, 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" @@ -2527,6 +2900,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" @@ -2537,6 +2911,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" @@ -2546,16 +2921,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" @@ -2565,6 +2954,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" @@ -2593,6 +2983,7 @@ ethers@^4.0.7: 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" @@ -2601,13 +2992,15 @@ 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" -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" @@ -2615,6 +3008,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" @@ -2622,18 +3016,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" @@ -2641,6 +3039,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" @@ -2653,12 +3052,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" @@ -2671,12 +3072,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" @@ -2712,12 +3115,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" @@ -2729,6 +3134,7 @@ extend@~3.0.2: 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" @@ -2743,12 +3149,14 @@ 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" @@ -2759,67 +3167,88 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" + integrity sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q== + dependencies: + esprima-extract-comments "^1.1.0" + parse-code-context "^1.0.0" + 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" @@ -2827,22 +3256,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" @@ -2853,6 +3287,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" @@ -2862,6 +3297,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" @@ -2874,6 +3310,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" @@ -2881,67 +3318,79 @@ 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" + combined-stream "^1.0.6" mime-types "^2.1.12" 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" @@ -2952,21 +3401,24 @@ 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" +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" 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" @@ -2975,12 +3427,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" @@ -2990,6 +3444,7 @@ 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" @@ -2998,6 +3453,7 @@ fs@0.0.2: 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" @@ -3005,6 +3461,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" @@ -3014,20 +3471,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" +ganache-cli@^6.2.4: + 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" @@ -3041,10 +3504,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" @@ -3052,20 +3517,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" @@ -3073,12 +3542,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" @@ -3086,6 +3557,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" @@ -3097,6 +3569,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" @@ -3104,9 +3577,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" @@ -3118,6 +3592,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" @@ -3128,32 +3603,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" @@ -3171,24 +3639,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" @@ -3199,53 +3672,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" @@ -3254,6 +3738,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" @@ -3262,10 +3747,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" @@ -3273,12 +3760,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" @@ -3291,8 +3780,9 @@ 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" @@ -3300,6 +3790,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" @@ -3308,10 +3799,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" @@ -3320,6 +3813,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" @@ -3327,10 +3821,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" @@ -3340,10 +3836,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" @@ -3352,10 +3850,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" @@ -3367,26 +3867,31 @@ 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" @@ -3401,6 +3906,7 @@ ignore@^5.0.2: 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" @@ -3408,22 +3914,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" @@ -3431,14 +3942,17 @@ 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@^6.1.0: version "6.2.0" @@ -3461,76 +3975,91 @@ inquirer@^6.1.0: 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" @@ -3539,6 +4068,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" @@ -3547,210 +4077,230 @@ 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-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" - -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" @@ -3758,10 +4308,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" @@ -3781,6 +4333,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" @@ -3788,30 +4341,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", 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" @@ -3819,22 +4379,27 @@ 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-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" @@ -3846,68 +4411,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" @@ -3917,6 +4496,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" @@ -3926,6 +4506,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" @@ -3933,62 +4514,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" @@ -3998,6 +4591,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" @@ -4005,6 +4599,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" @@ -4017,6 +4612,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" @@ -4024,6 +4620,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" @@ -4034,6 +4631,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" @@ -4043,10 +4641,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" @@ -4055,6 +4655,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" @@ -4062,44 +4663,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.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= 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" + 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" @@ -4107,48 +4718,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" @@ -4165,16 +4785,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" @@ -4186,6 +4809,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" @@ -4199,6 +4823,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" @@ -4206,14 +4831,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" @@ -4227,6 +4855,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" @@ -4237,10 +4866,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" @@ -4259,6 +4890,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" @@ -4277,80 +4909,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.36.0" + 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" @@ -4358,12 +5006,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: 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" @@ -4380,6 +5030,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" @@ -4395,6 +5046,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" @@ -4411,51 +5063,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" @@ -4464,18 +5127,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.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.0.tgz#9d443fdb5e13a20770cc5e602eee59760a685885" + integrity sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw== 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" @@ -4492,14 +5159,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" @@ -4508,14 +5178,17 @@ 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" + version "2.6.0" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" + integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== 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" @@ -4524,10 +5197,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" @@ -4535,6 +5210,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" @@ -4542,6 +5218,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" @@ -4570,6 +5247,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" @@ -4583,22 +5261,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" @@ -4606,6 +5287,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" @@ -4615,16 +5297,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" @@ -4632,12 +5317,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" @@ -4647,10 +5334,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" @@ -4658,14 +5347,17 @@ 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" @@ -4674,24 +5366,29 @@ 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" @@ -4699,40 +5396,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@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.0.0.tgz#b45dddbdae090f89577598c1a7e7518df61b7ba2" +openzeppelin-solidity@^2.1.0-rc.2: + version "2.1.0-rc.2" + resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.1.0-rc.2.tgz#704b7c86cc45fc82bc23ab706d767d04cf3391dc" + integrity sha512-2Yf0c4k1v0L354ZXobBn6wL207fBw+906icm4F0DYix4U+4fUMA2xgjWzVFi6zdJKZnCgBRkg+eddF8ZZY6gNA== 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" @@ -4740,6 +5444,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" @@ -4751,24 +5456,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" @@ -4777,10 +5487,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" @@ -4788,40 +5500,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" + version "1.0.7" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.7.tgz#2473439021b57f1516c82f58be7275ad8ef1bb27" + integrity sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ== 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" @@ -4829,9 +5549,15 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" +parse-code-context@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" + integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA== + 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" @@ -4841,6 +5567,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" @@ -4848,58 +5575,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: +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: 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" @@ -4908,12 +5648,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" @@ -4924,98 +5666,138 @@ 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= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== 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-plugin-solidity-refactor@^1.0.0-alpha.10: + version "1.0.0-alpha.10" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity-refactor/-/prettier-plugin-solidity-refactor-1.0.0-alpha.10.tgz#39c783d9bae100792a71dbd9b60277fbc5cfa31b" + integrity sha512-xHZOIbYD1NYsacpGuPuCbwDbiU5nT07YPrRhkMsuulVocy15vL+XQLFyQmU+oMgeQuQLI8vW79QYw32SG08RbA== + dependencies: + emoji-regex "^7.0.1" + escape-string-regexp "^1.0.5" + extract-comments "^1.1.0" + prettier "^1.15.2" + solidity-parser-antlr "^0.3.1" + string-width "3.0.0" + +prettier@^1.15.2, 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.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" + 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" @@ -5023,6 +5805,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" @@ -5034,6 +5817,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" @@ -5041,6 +5825,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" @@ -5048,18 +5833,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" @@ -5071,22 +5860,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: +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" @@ -5095,14 +5889,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" + 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" @@ -5111,12 +5908,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" @@ -5124,14 +5923,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" @@ -5141,6 +5943,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" @@ -5148,26 +5951,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.6.3" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0" + integrity sha512-8ugJWRCWLGXy+7PmNh8WJz3g1TaTUt1XyoIcFN+x0Zbkoz+KKdUyx1AQLYJdbFXjuF41Nmjn5+j//rxvhFjgSQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - schedule "^0.5.0" + scheduler "^0.11.2" react@^16.2.0: - version "16.5.2" - resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" + version "16.6.3" + resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c" + integrity sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - schedule "^0.5.0" + scheduler "^0.11.2" 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" @@ -5175,6 +5981,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" @@ -5182,6 +5989,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" @@ -5190,6 +5998,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" @@ -5198,12 +6007,14 @@ 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" @@ -5213,6 +6024,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.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" @@ -5225,6 +6037,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" @@ -5234,6 +6047,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" @@ -5242,28 +6056,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" @@ -5272,23 +6092,26 @@ 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@^2.0.0, regexpp@^2.0.1: +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" 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" @@ -5297,52 +6120,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" @@ -5352,6 +6185,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" @@ -5377,18 +6211,27 @@ 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-from-string@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 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" @@ -5396,34 +6239,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" + 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" @@ -5431,32 +6281,38 @@ 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" + 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.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" @@ -5464,18 +6320,21 @@ 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== rxjs@^6.1.0: version "6.3.3" @@ -5486,54 +6345,65 @@ rxjs@^6.1.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.11.2: + version "0.11.3" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.3.tgz#b5769b90cf8b1464f3f3cfcafe8e3cd7555a2d6b" + integrity sha512-i9X9VRRVZDd3xZw10NY5Z2cVMbdYg6gqFecfj79USv1CFN+YrJ3gIPRKf1qlY+Sxly4djoKdfx1T+m9dnRB8kQ== dependencies: + loose-envify "^1.1.0" 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.4: version "2.0.4" @@ -5542,6 +6412,7 @@ scrypt-js@2.0.4: 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" @@ -5549,18 +6420,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" @@ -5574,24 +6448,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" @@ -5610,6 +6489,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" @@ -5619,6 +6499,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" @@ -5629,14 +6510,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" @@ -5646,6 +6530,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" @@ -5655,18 +6540,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" @@ -5674,30 +6563,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: - 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" @@ -5706,14 +6600,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" @@ -5722,16 +6619,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" @@ -5740,12 +6642,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" @@ -5759,39 +6663,46 @@ 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" + 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" +solc@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.0.tgz#2deb2ae992acac3afb909f85c38d00f01dcb335e" + integrity sha512-mdLHDl9WeYrN+FIKcMc9PlPfnA9DG9ur5QpCDKcv6VC4RINAsTF4EMuXMZMKoQTvZhtLyJIVH/BZ+KU830Z8Xg== dependencies: fs-extra "^0.30.0" + keccak "^1.0.2" memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" + require-from-string "^2.0.0" + semver "^5.5.0" + yargs "^11.0.0" -solc@^0.4.19, solc@^0.4.2, solc@^0.4.24: +solc@^0.4.19, 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" @@ -5802,6 +6713,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" @@ -5817,6 +6729,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" @@ -5826,9 +6739,15 @@ solidity-docgen@^0.1.0: react-dom "^16.2.0" shelljs "^0.8.1" +solidity-parser-antlr@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.3.2.tgz#1cf9d019280550a31299dc380e87a310dc4ca154" + integrity sha512-aO/lbnc14A81cQigN5sKNuwbxohPyJOq7kpLirYT/6emCw5Gjb0TJoZ3TzL1tYdIX6gjTAMlQ1UZwOcrzOAp4w== + 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" @@ -5837,10 +6756,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" @@ -5858,6 +6779,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" @@ -5866,14 +6788,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" @@ -5881,40 +6806,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: 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" @@ -5922,35 +6854,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" @@ -5965,10 +6904,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" @@ -5976,22 +6917,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" @@ -5999,6 +6945,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" @@ -6009,10 +6956,21 @@ 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-width@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" + integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.0.0" 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" @@ -6021,6 +6979,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" @@ -6028,100 +6987,132 @@ 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: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" +string_decoder@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== 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= + +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@^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" @@ -6147,12 +7138,14 @@ table@^5.0.2: 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" + version "0.2.9" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8" + integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== 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" @@ -6171,6 +7164,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" @@ -6183,6 +7177,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" @@ -6193,19 +7188,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" @@ -6213,6 +7210,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" @@ -6220,36 +7218,43 @@ 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-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" @@ -6257,6 +7262,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" @@ -6267,30 +7273,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" @@ -6298,38 +7310,53 @@ 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" + 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" @@ -6338,6 +7365,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" @@ -6348,6 +7376,7 @@ 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.2.0: version "0.2.0" @@ -6361,18 +7390,21 @@ truffle-hdwallet-provider-privkey@0.2.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" web3-provider-engine "^8.4.0" -truffle@4.1.14: - version "4.1.14" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" +truffle@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.0.tgz#2e4e2eedc5583ae38c7227585e5177d6360fbc6d" + integrity sha512-la0TJu+E59Ut62i6cGY0sugeubglDqH5w49a7IrpxZ1nnsDqv6qWB3ibiyYiCp/jr+iI0bLtcr3DKkfQjVDd+g== dependencies: + app-module-path "^2.2.0" mocha "^4.1.0" original-require "1.0.1" - solc "0.4.24" + solc "0.5.0" tslib@^1.9.0: version "1.9.3" @@ -6381,30 +7413,36 @@ tslib@^1.9.0: 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" @@ -6412,26 +7450,31 @@ 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" 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" @@ -6441,6 +7484,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" @@ -6448,10 +7492,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" @@ -6460,10 +7506,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" @@ -6471,14 +7519,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" @@ -6488,18 +7539,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: +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" @@ -6507,34 +7562,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" @@ -6542,38 +7604,46 @@ 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" + integrity sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo= dependencies: async "~0.9.0" deep-equal "~0.2.1" @@ -6585,22 +7655,27 @@ 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== 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" @@ -6608,14 +7683,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" @@ -6624,12 +7702,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" @@ -6638,6 +7718,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" @@ -6651,6 +7732,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" @@ -6659,6 +7741,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" @@ -6667,6 +7750,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" @@ -6677,6 +7761,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" @@ -6684,6 +7769,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" @@ -6694,6 +7780,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" @@ -6702,6 +7789,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" @@ -6711,6 +7799,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" @@ -6720,6 +7809,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" @@ -6735,6 +7825,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" @@ -6748,6 +7839,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" @@ -6755,6 +7847,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" @@ -6765,6 +7858,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" @@ -6782,6 +7876,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" @@ -6790,6 +7885,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" @@ -6814,6 +7910,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" @@ -6833,6 +7930,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" @@ -6840,6 +7938,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" @@ -6848,6 +7947,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" @@ -6856,6 +7956,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" @@ -6865,6 +7966,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" @@ -6877,6 +7979,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" @@ -6887,6 +7990,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" @@ -6897,6 +8001,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" @@ -6907,6 +8012,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" @@ -6919,6 +8025,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" @@ -6928,6 +8035,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" @@ -6938,6 +8046,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" @@ -6948,6 +8057,7 @@ web3@^0.20.6: 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" @@ -6955,6 +8065,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" @@ -6991,38 +8102,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" + 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" @@ -7035,6 +8154,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" @@ -7046,18 +8166,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" @@ -7065,16 +8189,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" @@ -7083,12 +8210,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" @@ -7101,16 +8230,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" @@ -7124,40 +8256,49 @@ 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" @@ -7165,24 +8306,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" +yargs@11.1.0, 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" @@ -7195,11 +8340,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" @@ -7212,11 +8358,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" @@ -7236,6 +8383,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" @@ -7254,6 +8402,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" @@ -7263,6 +8412,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 4a27fe25cc0f6cda37d11de5e5000e8cc1718086 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 11 Jan 2019 15:04:42 +0530 Subject: [PATCH 054/119] Test cases for data store --- test/za_datastore.js | 125 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 test/za_datastore.js diff --git a/test/za_datastore.js b/test/za_datastore.js new file mode 100644 index 000000000..6f6702da4 --- /dev/null +++ b/test/za_datastore.js @@ -0,0 +1,125 @@ +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +contract("Data store", async (accounts) => { + describe("Should attach to security token securely", async () => { + it("Should be attached to a security token upon deployment", async () => { + + }); + + it("Should not allow non-issuer to change security token address", async () => { + + }); + + it("Should not allow DATA module to change security token address", async () => { + + }); + + it("Should allow issuer to change security token address", async () => { + + }); + }); + + describe("Should not allow unautohrized modification to data", async () => { + it("Should not allow random addresses to modify data", async () => { + + }); + + it("Should not allow modules that does not belong to DATA type to modify data", async () => { + + }); + + it("Should not allow archived modules to modify data", async () => { + + }); + }); + + describe("Should set data correctly", async () => { + it("Should set uint256 correctly", async () => { + + }); + + it("Should set bytes32 correctly", async () => { + + }); + + it("Should set address correctly", async () => { + + }); + + it("Should set string correctly", async () => { + + }); + + it("Should set bytes correctly", async () => { + + }); + + it("Should set bool correctly", async () => { + + }); + + it("Should set uint256 array correctly", async () => { + + }); + + it("Should set bytes32 array correctly", async () => { + + }); + + it("Should set address array correctly", async () => { + + }); + + it("Should set bool array correctly", async () => { + + }); + }); + + describe("Should fetch data correctly", async () => { + it("Should fetch uint256 correctly", async () => { + + }); + + it("Should fetch bytes32 correctly", async () => { + + }); + + it("Should fetch address correctly", async () => { + + }); + + it("Should fetch string correctly", async () => { + + }); + + it("Should fetch bytes correctly", async () => { + + }); + + it("Should fetch bool correctly", async () => { + + }); + + it("Should fetch uint256 array correctly", async () => { + + }); + + it("Should fetch bytes32 array correctly", async () => { + + }); + + it("Should fetch address array correctly", async () => { + + }); + + it("Should fetch bool array correctly", async () => { + + }); + + it("Should fetch multiple data types in a single call correctly", async () => { + + }); + }); +}); \ No newline at end of file From 0dd7ce32c09953328404e9978f9f8adeaa4d39d6 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 11 Jan 2019 16:20:11 +0530 Subject: [PATCH 055/119] Rebase conflicts resolved --- contracts/DataStore.sol | 119 ++++++++++++++++++++++++ contracts/interfaces/ISecurityToken.sol | 7 ++ contracts/tokens/SecurityToken.sol | 11 ++- test/za_datastore.js | 4 - 4 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 contracts/DataStore.sol diff --git a/contracts/DataStore.sol b/contracts/DataStore.sol new file mode 100644 index 000000000..048cfa3b5 --- /dev/null +++ b/contracts/DataStore.sol @@ -0,0 +1,119 @@ +pragma solidity ^0.5.0; + +import "./interfaces/ISecurityToken.sol"; +import "./interfaces/IOwnable.sol"; + +contract DataStore { + ISecurityToken public associatedToken; + + mapping (bytes32 => uint256) internal uintData; + mapping (bytes32 => bytes32) internal bytes32Data; + mapping (bytes32 => address) internal addressData; + mapping (bytes32 => string) internal stringData; + mapping (bytes32 => bytes) internal bytesData; + mapping (bytes32 => bool) internal boolData; + mapping (bytes32 => uint256[]) internal uintArrayData; + mapping (bytes32 => bytes32[]) internal bytes32ArrayData; + mapping (bytes32 => address[]) internal addressArrayData; + mapping (bytes32 => bool[]) internal boolArrayData; + + uint8 constant DATA_KEY = 10; + + modifier onlyDataModuleWithValidKey(bytes32 _key) { + require(_key != bytes32(0), "Missing key"); + require(associatedToken.isModule(msg.sender, DATA_KEY), "Unauthorized"); + _; + } + + modifier onlyOwner() { + require(msg.sender == IOwnable(address(associatedToken)).owner(), "Unauthorized"); + _; + } + + function setSecurityToken(address _securityToken) public { + if(address(associatedToken) != address(0)) { + require(msg.sender == IOwnable(address(associatedToken)).owner(), "Unauthorized"); + } + associatedToken = ISecurityToken(_securityToken); + } + + function setData(bytes32 _key, uint256 _data) external onlyDataModuleWithValidKey(_key) { + uintData[_key] = _data; + } + + function setData(bytes32 _key, bytes32 _data) external onlyDataModuleWithValidKey(_key) { + bytes32Data[_key] = _data; + } + + function setData(bytes32 _key, address _data) external onlyDataModuleWithValidKey(_key) { + addressData[_key] = _data; + } + + function setData(bytes32 _key, string calldata _data) external onlyDataModuleWithValidKey(_key) { + stringData[_key] = _data; + } + + function setData(bytes32 _key, bytes calldata _data) external onlyDataModuleWithValidKey(_key) { + bytesData[_key] = _data; + } + + function setData(bytes32 _key, bool _data) external onlyDataModuleWithValidKey(_key) { + boolData[_key] = _data; + } + + function setData(bytes32 _key, uint256[] calldata _data) external onlyDataModuleWithValidKey(_key) { + uintArrayData[_key] = _data; + } + + function setData(bytes32 _key, bytes32[] calldata _data) external onlyDataModuleWithValidKey(_key) { + bytes32ArrayData[_key] = _data; + } + + function setData(bytes32 _key, address[] calldata _data) external onlyDataModuleWithValidKey(_key) { + addressArrayData[_key] = _data; + } + + function setData(bytes32 _key, bool[] calldata _data) external onlyDataModuleWithValidKey(_key) { + boolArrayData[_key] = _data; + } + + function getUint(bytes32 _key) external view returns(uint256) { + return uintData[_key]; + } + + function getBytes32(bytes32 _key) external view returns(bytes32) { + return bytes32Data[_key]; + } + + function getAddress(bytes32 _key) external view returns(address) { + return addressData[_key]; + } + + function getString(bytes32 _key) external view returns(string memory) { + return stringData[_key]; + } + + function getBytes(bytes32 _key) external view returns(bytes memory) { + return bytesData[_key]; + } + + function getBool(bytes32 _key) external view returns(bool) { + return boolData[_key]; + } + + function getUintArray(bytes32 _key) external view returns(uint256[] memory) { + return uintArrayData[_key]; + } + + function getBytes32Array(bytes32 _key) external view returns(bytes32[] memory) { + return bytes32ArrayData[_key]; + } + + function getAddressArray(bytes32 _key) external view returns(address[] memory) { + return addressArrayData[_key]; + } + + function getBoolArray(bytes32 _key) external view returns(bool[] memory) { + return boolArrayData[_key]; + } +} diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index f280d6c19..2bdbf6339 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -21,6 +21,13 @@ interface ISecurityToken { //transfer, transferFrom must respect the result of verifyTransfer function verifyTransfer(address _from, address _to, uint256 _value) external returns (bool success); + /** + * @notice Checks if an address is a module of certain type + * @param _module Address to check + * @param _type type to check against + */ + function isModule(address _module, uint8 _type) external view returns(bool); + /** * @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) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 3c27d7d94..5e05891a0 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -734,7 +734,16 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater return false; } - function _checkAndBurn(address _from, uint256 _value, bytes _data) internal returns(bool) { + /** + * @notice Checks if an address is a module of certain type + * @param _module Address to check + * @param _type type to check against + */ + function isModule(address _module, uint8 _type) public view returns(bool) { + return _isModule(_module, _type); + } + + function _checkAndBurn(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); _adjustTotalSupplyCheckpoints(); _burn(_from, _value); diff --git a/test/za_datastore.js b/test/za_datastore.js index 6f6702da4..9b590e78f 100644 --- a/test/za_datastore.js +++ b/test/za_datastore.js @@ -117,9 +117,5 @@ contract("Data store", async (accounts) => { it("Should fetch bool array correctly", async () => { }); - - it("Should fetch multiple data types in a single call correctly", async () => { - - }); }); }); \ No newline at end of file From f1ef7c2f40beb23aca01bbc80424d479aa594068 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 14 Jan 2019 11:51:52 +0530 Subject: [PATCH 056/119] wip ds proxy --- contracts/{ => datastore}/DataStore.sol | 7 +++--- contracts/datastore/DataStoreFactory.sol | 18 +++++++++++++++ contracts/datastore/DataStoreStorage.sol | 20 ++++++++++++++++ contracts/proxy/DataStoreProxy.sol | 29 ++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) rename contracts/{ => datastore}/DataStore.sol (96%) create mode 100644 contracts/datastore/DataStoreFactory.sol create mode 100644 contracts/datastore/DataStoreStorage.sol create mode 100644 contracts/proxy/DataStoreProxy.sol diff --git a/contracts/DataStore.sol b/contracts/datastore/DataStore.sol similarity index 96% rename from contracts/DataStore.sol rename to contracts/datastore/DataStore.sol index 048cfa3b5..b639d18ba 100644 --- a/contracts/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -1,9 +1,10 @@ pragma solidity ^0.5.0; -import "./interfaces/ISecurityToken.sol"; -import "./interfaces/IOwnable.sol"; +import "../interfaces/ISecurityToken.sol"; +import "../interfaces/IOwnable.sol"; +import "./DataStoreStorage.sol"; -contract DataStore { +contract DataStore is DataStoreStorage { ISecurityToken public associatedToken; mapping (bytes32 => uint256) internal uintData; diff --git a/contracts/datastore/DataStoreFactory.sol b/contracts/datastore/DataStoreFactory.sol new file mode 100644 index 000000000..f4a3cc6d2 --- /dev/null +++ b/contracts/datastore/DataStoreFactory.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.0; + +import "../proxy/DataStoreProxy.sol"; + +contract DataStoreFactory { + + address public implementation; + + constructor(address _implementation) public { + require(_implementation != address(0), "Address should not be 0x"); + implementation = _implementation; + } + + function generateDataStore(address _securityToken) public returns (address) { + DataStoreProxy dsProxy = new DataStoreProxy(_securityToken, implementation); + return address(dsProxy); + } +} diff --git a/contracts/datastore/DataStoreStorage.sol b/contracts/datastore/DataStoreStorage.sol new file mode 100644 index 000000000..2dba41ede --- /dev/null +++ b/contracts/datastore/DataStoreStorage.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.5.0; + +import "../interfaces/ISecurityToken.sol"; + +contract DataStoreStorage { + ISecurityToken public associatedToken; + + mapping (bytes32 => uint256) internal uintData; + mapping (bytes32 => bytes32) internal bytes32Data; + mapping (bytes32 => address) internal addressData; + mapping (bytes32 => string) internal stringData; + mapping (bytes32 => bytes) internal bytesData; + mapping (bytes32 => bool) internal boolData; + mapping (bytes32 => uint256[]) internal uintArrayData; + mapping (bytes32 => bytes32[]) internal bytes32ArrayData; + mapping (bytes32 => address[]) internal addressArrayData; + mapping (bytes32 => bool[]) internal boolArrayData; + + uint8 constant DATA_KEY = 10; +} diff --git a/contracts/proxy/DataStoreProxy.sol b/contracts/proxy/DataStoreProxy.sol new file mode 100644 index 000000000..eaeb64a3a --- /dev/null +++ b/contracts/proxy/DataStoreProxy.sol @@ -0,0 +1,29 @@ +pragma solidity ^0.5.0; + +import "./OwnedProxy.sol"; +import "../DataStore/DataStoreStorage.sol"; + +/** + * @title DataStoreProxy Proxy + */ +contract DataStoreProxy is DataStoreStorage, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _implementation representing the address of the new implementation to be set + */ + constructor( + address _securityToken, + address _implementation + ) + public + { + require(_implementation != address(0) && _securityToken != address(0), + "Address should not be 0x" + ); + associatedToken = ISecurityToken(_securityToken); + __implementation = _implementation; + } + +} From cbce1306548cb8d299f52759ac9265086cf9d85a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 14 Jan 2019 12:22:50 +0530 Subject: [PATCH 057/119] DS deployment --- contracts/datastore/DataStore.sol | 14 - contracts/proxy/DataStoreProxy.sol | 2 +- contracts/tokens/STFactory.sol | 12 +- contracts/tokens/SecurityToken.sol | 29 +- migrations/2_deploy_contracts.js | 545 ++++++++++++++++++----------- 5 files changed, 372 insertions(+), 230 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index b639d18ba..0ef45bf13 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -5,20 +5,6 @@ import "../interfaces/IOwnable.sol"; import "./DataStoreStorage.sol"; contract DataStore is DataStoreStorage { - ISecurityToken public associatedToken; - - mapping (bytes32 => uint256) internal uintData; - mapping (bytes32 => bytes32) internal bytes32Data; - mapping (bytes32 => address) internal addressData; - mapping (bytes32 => string) internal stringData; - mapping (bytes32 => bytes) internal bytesData; - mapping (bytes32 => bool) internal boolData; - mapping (bytes32 => uint256[]) internal uintArrayData; - mapping (bytes32 => bytes32[]) internal bytes32ArrayData; - mapping (bytes32 => address[]) internal addressArrayData; - mapping (bytes32 => bool[]) internal boolArrayData; - - uint8 constant DATA_KEY = 10; modifier onlyDataModuleWithValidKey(bytes32 _key) { require(_key != bytes32(0), "Missing key"); diff --git a/contracts/proxy/DataStoreProxy.sol b/contracts/proxy/DataStoreProxy.sol index eaeb64a3a..6d2ce2482 100644 --- a/contracts/proxy/DataStoreProxy.sol +++ b/contracts/proxy/DataStoreProxy.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.0; import "./OwnedProxy.sol"; -import "../DataStore/DataStoreStorage.sol"; +import "../datastore/DataStoreStorage.sol"; /** * @title DataStoreProxy Proxy diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index 85153e816..3ae47f9b7 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -2,6 +2,7 @@ pragma solidity ^0.4.24; import "./SecurityToken.sol"; import "../interfaces/ISTFactory.sol"; +import "../datastore/DataStoreFactory.sol"; /** * @title Proxy for deploying SecurityToken instances @@ -9,9 +10,11 @@ import "../interfaces/ISTFactory.sol"; contract STFactory is ISTFactory { address public transferManagerFactory; + DataStoreFactory public dataStoreFactory; - constructor (address _transferManagerFactory) public { + constructor(address _transferManagerFactory, address _dataStoreFactory) public { transferManagerFactory = _transferManagerFactory; + dataStoreFactory = DataStoreFactory(_dataStoreFactory); } /** @@ -35,8 +38,9 @@ contract STFactory is ISTFactory { _tokenDetails, _polymathRegistry ); - SecurityToken(newSecurityTokenAddress).addModule(transferManagerFactory, "", 0, 0); - SecurityToken(newSecurityTokenAddress).transferOwnership(_issuer); - return newSecurityTokenAddress; + newSecurityToken.addModule(transferManagerFactory, "", 0, 0); + newSecurityToken.setDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); + newSecurityToken.transferOwnership(_issuer); + return address(newSecurityToken); } } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 5e05891a0..b31ffe3e8 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -46,6 +46,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint8 constant MINT_KEY = 3; uint8 constant CHECKPOINT_KEY = 4; uint8 constant BURN_KEY = 5; + uint8 constant DATA_KEY = 10; uint256 public granularity; @@ -64,6 +65,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Address whitelisted by issuer as controller address public controller; + address public dataStore; + // Records added modules - module list should be order agnostic! mapping (uint8 => address[]) modules; @@ -211,20 +214,24 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater updateFromRegistry(); tokenDetails = _tokenDetails; granularity = _granularity; - securityTokenVersion = SemanticVersion(2,0,0); + securityTokenVersion = SemanticVersion(2, 0, 0); } - // /** - // * @notice Attachs a module to the SecurityToken - // * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it - // * @dev to control restrictions on transfers. - // * @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 the module. - // * @param _budget max amount of ongoing POLY willing to assign to the module. - // * @param _label custom module label. - // */ + function setDataStore(address _dataStore) public { + require(_dataStore != address(0), "Invalid address"); + dataStore = _dataStore; + } + /** + * @notice Attachs a module to the SecurityToken + * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it + * @dev to control restrictions on transfers. + * @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 the module. + * @param _budget max amount of ongoing POLY willing to assign to the module. + * @param _label custom module label. + */ function addModuleWithLabel( address _moduleFactory, bytes _data, diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 14bdf9fed..79a99b20d 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,29 +1,42 @@ -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 USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); -const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') -const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') -const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); -const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); -const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol') -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 FeatureRegistry = artifacts.require('./FeatureRegistry.sol') -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 SecurityToken = artifacts.require('./tokens/SecurityToken.sol') +const PolymathRegistry = artifacts.require("./PolymathRegistry.sol"); +const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager.sol"); +const GeneralPermissionManagerLogic = artifacts.require("./GeneralPermissionManager.sol"); +const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); +const PercentageTransferManagerLogic = artifacts.require("./PercentageTransferManager.sol"); +const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); +const USDTieredSTOLogic = artifacts.require("./USDTieredSTO.sol"); +const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); +const CountTransferManagerLogic = artifacts.require("./CountTransferManager.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"); +const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); +const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); +const ManualApprovalTransferManagerLogic = artifacts.require("./ManualApprovalTransferManager.sol"); +const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); +const CappedSTOLogic = artifacts.require("./CappedSTO.sol"); +const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); +const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); +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 SecurityToken = artifacts.require("./tokens/SecurityToken.sol"); +const STRGetter = artifacts.require('./STRGetter.sol'); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); -let BigNumber = require('bignumber.js'); -const cappedSTOSetupCost = new BigNumber(20000).times(new BigNumber(10).pow(18)); // 20K POLY fee -const usdTieredSTOSetupCost = new BigNumber(100000).times(new BigNumber(10).pow(18)); // 100K POLY fee -const initRegFee = new BigNumber(250).times(new BigNumber(10).pow(18)); // 250 POLY fee for registering ticker or security token in registry +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const nullAddress = "0x0000000000000000000000000000000000000000"; +const cappedSTOSetupCost = new BN(20000).mul(new BN(10).pow(new BN(18))); // 20K POLY fee +const usdTieredSTOSetupCost = new BN(100000).mul(new BN(10).pow(new BN(18))); // 100K POLY fee +const initRegFee = new BN(250).mul(new BN(10).pow(new BN(18))); // 250 POLY fee for registering ticker or security token in registry let PolyToken; let UsdToken; let ETHOracle; @@ -121,181 +134,313 @@ module.exports = function (deployer, network, accounts) { }] }; - // POLYMATH NETWORK Configuration :: DO THIS ONLY ONCE - // A) Deploy the PolymathRegistry contract - return deployer.deploy(PolymathRegistry, {from: PolymathAccount}).then(() => { - return PolymathRegistry.deployed(); - }).then((_polymathRegistry) => { - polymathRegistry = _polymathRegistry; - return polymathRegistry.changeAddress("PolyToken", PolyToken, {from: PolymathAccount}); - }).then(() => { - // Deploy libraries - return deployer.deploy(TokenLib, {from: PolymathAccount}); - }).then(() => { - // Link libraries - deployer.link(TokenLib, SecurityToken); - deployer.link(TokenLib, STFactory); - // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) - return deployer.deploy(ModuleRegistry, {from: PolymathAccount}); - }).then(() => { - return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); - }).then(() => { - let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [polymathRegistry.address, PolymathAccount]); - return ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, {from: PolymathAccount}); - }).then(() => { - moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); - // Add module registry to polymath registry - return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.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) - 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) - return deployer.deploy(GeneralPermissionManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // 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 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 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}); - }).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}); - }).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) - return deployer.deploy(ManualApprovalTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. - return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // K) Deploy the FeatureRegistry contract to control feature switches - return deployer.deploy(FeatureRegistry, PolymathRegistry.address, {from: PolymathAccount}); - }).then(() => { - // Assign the address into the FeatureRegistry key - return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, {from: PolymathAccount}); - }).then(() => { - // J) Deploy the SecurityTokenRegistry contract (Used to hold the deployed secuirtyToken details. It also act as the interface to deploy the SecurityToken) - return deployer.deploy(SecurityTokenRegistry, {from: PolymathAccount}) - }).then(()=> { - return deployer.deploy(SecurityTokenRegistryProxy, {from: PolymathAccount}); - }).then(() => { - let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolyToken, PolymathAccount]); - return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); - }).then(() => { - // Assign the address into the SecurityTokenRegistry key - return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); - }).then(() => { - // Update all addresses into the registry contract by calling the function updateFromregistry - return moduleRegistry.updateFromRegistry({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. - return moduleRegistry.registerModule(PercentageTransferManagerFactory.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. - return moduleRegistry.registerModule(CountTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // 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(() => { - // 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(GeneralPermissionManagerFactory.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. - return moduleRegistry.registerModule(EtherDividendCheckpointFactory.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. - return moduleRegistry.registerModule(ManualApprovalTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // E) Register the ERC20DividendCheckpointFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the ERC20DividendCheckpoint contract. - return moduleRegistry.registerModule(ERC20DividendCheckpointFactory.address, {from: PolymathAccount}); - }).then(() => { - // F) Once the GeneralTransferManagerFactory 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(GeneralTransferManagerFactory.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(() => { - // 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. - // 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 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. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(GeneralPermissionManagerFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // G) Once the EtherDividendCheckpointFactory 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(EtherDividendCheckpointFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the ERC20DividendCheckpointFactory 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(ERC20DividendCheckpointFactory.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. - // 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(() => { - // 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}) - }).then(() => { - // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the CappedSTOFactory contract. - return moduleRegistry.registerModule(CappedSTOFactory.address, {from: PolymathAccount}) - }).then(()=>{ - // G) Once the CappedSTOFactory 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(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}) - }).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. - return moduleRegistry.registerModule(USDTieredSTOFactory.address, {from: PolymathAccount}) - }).then(()=>{ - // J) Once the USDTieredSTOFactory 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(USDTieredSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - return polymathRegistry.changeAddress("PolyUsdOracle", POLYOracle, {from: PolymathAccount}); - }).then(() => { - return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, {from: PolymathAccount}); - }).then(() => { - return deployer.deploy(SecurityToken, 'a', 'a', 18, 1, 'a', polymathRegistry.address, {from: PolymathAccount}); - }).then(() => { - console.log('\n'); - console.log(` + // POLYMATH NETWORK Configuration :: DO THIS ONLY ONCE + // A) Deploy the PolymathRegistry contract + return deployer + .deploy(PolymathRegistry, { from: PolymathAccount }) + .then(() => { + return PolymathRegistry.deployed(); + }) + .then(_polymathRegistry => { + polymathRegistry = _polymathRegistry; + return polymathRegistry.changeAddress("PolyToken", PolyToken, { from: PolymathAccount }); + }) + .then(() => { + // Deploy libraries + return deployer.deploy(TokenLib, { from: PolymathAccount }); + }) + .then(() => { + // Link libraries + deployer.link(TokenLib, SecurityToken); + deployer.link(TokenLib, STFactory); + // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) + return deployer.deploy(ModuleRegistry, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(ModuleRegistryProxy, { from: PolymathAccount }); + }) + .then(() => { + return ModuleRegistryProxy.at(ModuleRegistryProxy.address); + }) + .then(moduleRegistryProxy => { + let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [polymathRegistry.address, PolymathAccount]); + return moduleRegistryProxy.upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, { from: PolymathAccount }); + }) + .then(() => { + return ModuleRegistry.at(ModuleRegistryProxy.address); + }) + .then(moduleRegistryInstance => { + moduleRegistry = moduleRegistryInstance; + // 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, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the GeneralPermissionManagerLogic Contract (Factory used to generate the GeneralPermissionManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralPermissionManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the CountTransferManagerLogic Contract (Factory used to generate the CountTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(CountTransferManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the ManualApprovalTransferManagerLogic Contract (Factory used to generate the ManualApprovalTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(ManualApprovalTransferManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the PercentageTransferManagerLogic Contract (Factory used to generate the PercentageTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(PercentageTransferManagerLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // 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, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // 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, nullAddress, nullAddress, { 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, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the CappedSTOLogic Contract (Factory used to generate the CappedSTO contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(CappedSTOLogic, nullAddress, nullAddress, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the DataStoreLogic Contract + return deployer.deploy(DataStoreLogic, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the DataStoreFactory Contract + return deployer.deploy(DataStoreFactory, DataStoreLogic.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) + return deployer.deploy(GeneralTransferManagerFactory, new BN(0), new BN(0), new BN(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) + return deployer.deploy(GeneralPermissionManagerFactory, new BN(0), new BN(0), new BN(0), GeneralPermissionManagerLogic.address, { + from: PolymathAccount + }); + }) + .then(() => { + // 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, new BN(0), new BN(0), new BN(0), CountTransferManagerLogic.address, { + 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) + return deployer.deploy(PercentageTransferManagerFactory, new BN(0), new BN(0), new BN(0), PercentageTransferManagerLogic.address, { + 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) + return deployer.deploy(EtherDividendCheckpointFactory, new BN(0), new BN(0), new BN(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, new BN(0), new BN(0), new BN(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) + return deployer.deploy(ManualApprovalTransferManagerFactory, new BN(0), new BN(0), new BN(0), ManualApprovalTransferManagerLogic.address, { + from: PolymathAccount + }); + }) + .then(() => { + // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. + return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, DataStoreFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // K) Deploy the FeatureRegistry contract to control feature switches + return deployer.deploy(FeatureRegistry, PolymathRegistry.address, { from: PolymathAccount }); + }) + .then(() => { + // Assign the address into the FeatureRegistry key + return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, { from: PolymathAccount }); + }) + .then(() => { + // J) Deploy the SecurityTokenRegistry contract (Used to hold the deployed secuirtyToken details. It also act as the interface to deploy the SecurityToken) + return deployer.deploy(SecurityTokenRegistry, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(SecurityTokenRegistryProxy, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(STRGetter, {from: PolymathAccount}); + }) + .then(() => { + return SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address); + }) + .then((securityTokenRegistryProxy) => { + let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [ + PolymathRegistry.address, + STFactory.address, + initRegFee, + initRegFee, + PolymathAccount, + STRGetter.address + ]); + return securityTokenRegistryProxy.upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, { + from: PolymathAccount + }); + }) + .then(() => { + // Assign the address into the SecurityTokenRegistry key + return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, { from: PolymathAccount }); + }) + .then(() => { + // Update all addresses into the registry contract by calling the function updateFromregistry + return moduleRegistry.updateFromRegistry({ 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. + return moduleRegistry.registerModule(PercentageTransferManagerFactory.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. + return moduleRegistry.registerModule(CountTransferManagerFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // 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(() => { + // 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(GeneralPermissionManagerFactory.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. + return moduleRegistry.registerModule(EtherDividendCheckpointFactory.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. + return moduleRegistry.registerModule(ManualApprovalTransferManagerFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // E) Register the ERC20DividendCheckpointFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the ERC20DividendCheckpoint contract. + return moduleRegistry.registerModule(ERC20DividendCheckpointFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // F) Once the GeneralTransferManagerFactory 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(GeneralTransferManagerFactory.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(() => { + // 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. + // 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 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. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(GeneralPermissionManagerFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + // G) Once the EtherDividendCheckpointFactory 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(EtherDividendCheckpointFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + // G) Once the ERC20DividendCheckpointFactory 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(ERC20DividendCheckpointFactory.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. + // 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(() => { + // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). + return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, new BN(0), new BN(0), CappedSTOLogic.address, { from: PolymathAccount }); + }) + .then(() => { + // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the CappedSTOFactory contract. + return moduleRegistry.registerModule(CappedSTOFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // G) Once the CappedSTOFactory 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(CappedSTOFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). + return deployer.deploy(USDTieredSTOFactory, usdTieredSTOSetupCost, new BN(0), new BN(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. + return moduleRegistry.registerModule(USDTieredSTOFactory.address, { from: PolymathAccount }); + }) + .then(() => { + // J) Once the USDTieredSTOFactory 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(USDTieredSTOFactory.address, true, { from: PolymathAccount }); + }) + .then(() => { + return polymathRegistry.changeAddress("PolyUsdOracle", POLYOracle, { from: PolymathAccount }); + }) + .then(() => { + return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, { from: PolymathAccount }); + }) + .then(() => { + return deployer.deploy(SecurityToken, "a", "a", 18, 1, "a", polymathRegistry.address, { from: PolymathAccount }); + }) + .then(() => { + console.log("\n"); + console.log(` ----------------------- Polymath Network Smart Contracts: ----------------------- PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} From 12cb8dc70e888d50f541112102fd815590ca91af Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 14 Jan 2019 12:44:38 +0530 Subject: [PATCH 058/119] Fixed create instance helper --- test/helpers/createInstances.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 2021d350e..626fd91e5 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -30,6 +30,8 @@ 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 DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -140,7 +142,9 @@ async function deployGTM(account_polymath) { } async function deploySTFactory(account_polymath) { - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); + let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); assert.notEqual(I_STFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", "STFactory contract was not deployed"); From 535371bca54b5a3509520433f7810ffbcbe9cf9b Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 14 Jan 2019 13:00:54 +0530 Subject: [PATCH 059/119] tests fixed --- test/n_security_token_registry.js | 8 ++++++-- test/u_module_registry_proxy.js | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 9af7bd000..278eb268b 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -11,7 +11,9 @@ const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryPro const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); const STFactory = artifacts.require("./STFactory.sol"); - +const STRGetter = artifacts.require('./STRGetter.sol'); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -555,8 +557,10 @@ contract("SecurityTokenRegistry", accounts => { describe("Generate SecurityToken v2", async () => { it("Should deploy the st version 2", async () => { // Step 7: Deploy the STFactory contract + let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); + let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); - I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); assert.notEqual( I_STFactory002.address.valueOf(), diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 6d00b8fe2..657177051 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -11,6 +11,9 @@ const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); +const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -139,7 +142,9 @@ contract("ModuleRegistryProxy", accounts => { 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 }); + let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); + let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); assert.notEqual( I_STFactory.address.valueOf(), From a649748e0415f8b9480c0f38268bab8759e6b6f5 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 15 Jan 2019 11:19:51 +0530 Subject: [PATCH 060/119] Added KYC TM module --- contracts/interfaces/ISecurityToken.sol | 2 + .../TransferManager/KYCTransferManager.sol | 81 +++++++++++++++++++ .../KYCTransferManagerFactory.sol | 63 +++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 contracts/modules/Experimental/TransferManager/KYCTransferManager.sol create mode 100644 contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index 9ebfe160a..e1a0f104e 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -17,6 +17,8 @@ interface ISecurityToken { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); + function dataStore() external view returns (address); + /** * @notice Validates a transfer with a TransferManager module if it exists * @dev TransferManager module has a key of 2 diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol new file mode 100644 index 000000000..3c2075576 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -0,0 +1,81 @@ +pragma solidity ^0.5.0; + +import "../../TransferManager/TransferManager.sol"; +import "../../../datastore/DataStore.sol"; +import "../../../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract KYCTransferManager is TransferManager { + + using SafeMath for uint256; + + bytes32 public constant KYC_STATUS = "KYC_STATUS"; //We will standardize what key to use for what. + + bytes32 public constant KYC_PROVIDER = "KYC_PROVIDER"; + + /** + * @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); + } + + function verifyTransfer(address /*_from*/, address _to, uint256 /*_amount*/, bytes memory /* _data */, bool /* _isTransfer */) public returns(Result) { + if (!paused) { + bytes32 key = _getKYCKey(_to); + DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + if (dataStore.getBool(key)) + return Result.VALID; + } + return Result.NA; + } + + function modifyKYC( + address _investor, + bool _kycStatus + ) + public + withPerm(KYC_PROVIDER) + { + _modifyKYC(_investor, _kycStatus); + } + + function _modifyKYC( + address _investor, + bool _kycStatus + ) + internal + { + bytes32 key = _getKYCKey(_investor); + DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + dataStore.setData(key, _kycStatus); + } + + /** + * @notice Return the permissions flag that are associated with general trnasfer manager + */ + function getPermissions() public view returns(bytes32[] memory) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = KYC_PROVIDER; + return allPermissions; + } + + function _getKYCKey(address _identity) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(KYC_STATUS, _identity))); + } + +} diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol new file mode 100644 index 000000000..13c9bc5a2 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol @@ -0,0 +1,63 @@ +pragma solidity ^0.5.0; + +import "./KYCTransferManager.sol"; +import "./../../ModuleFactory.sol"; + + +contract KYCTransferManagerFactory is ModuleFactory { + + /** + * @notice Constructor + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "KYCTransferManager"; + title = "KYC Transfer Manager"; + description = "Manages KYC"; + 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 calldata /* _data */) external returns(address) { + address polyToken = _takeFee(); + KYCTransferManager kycTransferManager = new KYCTransferManager(msg.sender, polyToken); + /*solium-disable-next-line security/no-block-members*/ + emit GenerateModuleFromFactory(address(kycTransferManager), getName(), address(this), msg.sender, setupCost, now); + return address(kycTransferManager); + } + + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[] memory) { + 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 memory) { + /*solium-disable-next-line max-len*/ + return "pray it works"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[] memory) { + bytes32[] memory availableTags = new bytes32[](1); + availableTags[0] = "KYC"; + return availableTags; + } + +} From 6439b35dd92c1c95bddfe6469599605ec9851ea8 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 15 Jan 2019 11:45:44 +0530 Subject: [PATCH 061/119] Added array operation --- contracts/datastore/DataStore.sol | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 0ef45bf13..12b8374ee 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -64,6 +64,54 @@ contract DataStore is DataStoreStorage { boolArrayData[_key] = _data; } + function insertData(bytes32 _key, uint256 _data) external onlyDataModuleWithValidKey(_key) { + uintArrayData[_key].push(_data); + } + + function insertData(bytes32 _key, bytes32 _data) external onlyDataModuleWithValidKey(_key) { + bytes32ArrayData[_key].push(_data); + } + + function insertData(bytes32 _key, address _data) external onlyDataModuleWithValidKey(_key) { + addressArrayData[_key].push(_data); + } + + function insertData(bytes32 _key, bool _data) external onlyDataModuleWithValidKey(_key) { + boolArrayData[_key].push(_data); + } + + function deleteUint(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { + require(uintArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(uintArrayData[_key].length - 1 != _index) { + uintArrayData[_key][_index] = uintArrayData[_key][uintArrayData[_key].length - 1]; + } + uintArrayData[_key].length--; + } + + function deleteBytes32(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { + require(bytes32ArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(bytes32ArrayData[_key].length - 1 != _index) { + bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][uintArrayData[_key].length - 1]; + } + bytes32ArrayData[_key].length--; + } + + function deleteAddress(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { + require(addressArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(addressArrayData[_key].length - 1 != _index) { + addressArrayData[_key][_index] = addressArrayData[_key][uintArrayData[_key].length - 1]; + } + addressArrayData[_key].length--; + } + + function deleteBool(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { + require(boolArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(boolArrayData[_key].length - 1 != _index) { + boolArrayData[_key][_index] = boolArrayData[_key][uintArrayData[_key].length - 1]; + } + boolArrayData[_key].length--; + } + function getUint(bytes32 _key) external view returns(uint256) { return uintData[_key]; } @@ -103,4 +151,20 @@ contract DataStore is DataStoreStorage { function getBoolArray(bytes32 _key) external view returns(bool[] memory) { return boolArrayData[_key]; } + + function getUintArrayLength(bytes32 _key) external view returns(uint256) { + return uintArrayData[_key].length; + } + + function getBytes32ArrayLength(bytes32 _key) external view returns(uint256) { + return bytes32ArrayData[_key].length; + } + + function getAddressArrayLength(bytes32 _key) external view returns(uint256) { + return addressArrayData[_key].length; + } + + function getBoolArrayLength(bytes32 _key) external view returns(uint256) { + return boolArrayData[_key].length; + } } From bdba97596a01810d1548d7353f69323db3f5b62d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 15 Jan 2019 13:23:38 +0530 Subject: [PATCH 062/119] Added features --- contracts/datastore/DataStore.sol | 16 +++++ .../TransferManager/KYCTransferManager.sol | 59 +++++++++++++------ 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 12b8374ee..9d3ebabb3 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -167,4 +167,20 @@ contract DataStore is DataStoreStorage { function getBoolArrayLength(bytes32 _key) external view returns(uint256) { return boolArrayData[_key].length; } + + function getUintArrayElement(bytes32 _key, uint256 _index) external view returns(uint256) { + return uintArrayData[_key][_index]; + } + + function getBytes32ArrayElement(bytes32 _key, uint256 _index) external view returns(bytes32) { + return bytes32ArrayData[_key][_index]; + } + + function getAddressArrayElement(bytes32 _key, uint256 _index) external view returns(address) { + return addressArrayData[_key][_index]; + } + + function getBoolArrayElement(bytes32 _key, uint256 _index) external view returns(bool) { + return boolArrayData[_key][_index]; + } } diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol index 3c2075576..9c6d8ddd3 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -12,10 +12,12 @@ contract KYCTransferManager is TransferManager { using SafeMath for uint256; - bytes32 public constant KYC_STATUS = "KYC_STATUS"; //We will standardize what key to use for what. + bytes32 public constant KYC_NUMBER = "KYC_NUMBER"; //We will standardize what key to use for what. bytes32 public constant KYC_PROVIDER = "KYC_PROVIDER"; + bytes32 public constant KYC_ARRAY = "KYC_ARRAY"; + /** * @notice Constructor * @param _securityToken Address of the security token @@ -34,35 +36,42 @@ contract KYCTransferManager is TransferManager { return bytes4(0); } - function verifyTransfer(address /*_from*/, address _to, uint256 /*_amount*/, bytes memory /* _data */, bool /* _isTransfer */) public returns(Result) { + function verifyTransfer(address /*_from*/, address _to, uint256 /*_amount*/, bytes memory /* _data */, bool /* _isTransfer */) + public + returns (Result) + { if (!paused) { bytes32 key = _getKYCKey(_to); DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); - if (dataStore.getBool(key)) + if (dataStore.getUint(key) > 0) return Result.VALID; } return Result.NA; } - function modifyKYC( - address _investor, - bool _kycStatus - ) - public - withPerm(KYC_PROVIDER) - { + function modifyKYC( address _investor, bool _kycStatus) public withPerm(KYC_PROVIDER) { _modifyKYC(_investor, _kycStatus); } - function _modifyKYC( - address _investor, - bool _kycStatus - ) - internal - { - bytes32 key = _getKYCKey(_investor); + function _modifyKYC(address _investor, bool _kycStatus) internal { DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); - dataStore.setData(key, _kycStatus); + bytes32 key = _getKYCKey(_investor); + uint256 kycNumber = dataStore.getUint(key); //index in address array + 1 + uint256 kycTotal = dataStore.getAddressArrayLength(KYC_ARRAY); + if(_kycStatus) { + require(kycNumber == 0, "KYC exists"); + dataStore.setData(key, kycTotal + 1); + dataStore.insertData(KYC_ARRAY, _investor); + } else { + require(kycNumber != 0, "KYC does not exist"); + address lastAddress = dataStore.getAddressArrayElement(KYC_ARRAY, kycTotal - 1); + dataStore.deleteAddress(KYC_ARRAY, kycNumber - 1); + + //Corrects the index of last element as delete fucntions move last element to index. + dataStore.setData(_getKYCKey(lastAddress), kycNumber); + } + //Alternatively, we can just emit an event and not maintain the KYC array on chain. + //I am maintaining the array to showcase how it can be done in cases where it might be needed. } /** @@ -74,8 +83,20 @@ contract KYCTransferManager is TransferManager { return allPermissions; } + function getKYCAddresses() public view returns(address[] memory) { + DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + return dataStore.getAddressArray(KYC_ARRAY); + } + + function checkKYC(address _investor) public view returns (bool kyc) { + bytes32 key = _getKYCKey(_investor); + DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + if (dataStore.getUint(key) > 0) + kyc = true; + } + function _getKYCKey(address _identity) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(KYC_STATUS, _identity))); + return bytes32(keccak256(abi.encodePacked(KYC_NUMBER, _identity))); } } From c2c13367556d12f481d8fff4d28cc4a4bd64c86d Mon Sep 17 00:00:00 2001 From: tft Date: Tue, 15 Jan 2019 13:27:14 +0530 Subject: [PATCH 063/119] Invoked function _adjustTotalSupplyCheckpoints inside of createCheckpoint instead of mint/burn fucntions --- contracts/tokens/SecurityToken.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 2979a6a5d..3168037b2 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -648,7 +648,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater returns(bool success) { require(_updateTransfer(address(0), _investor, _value, _data), "Transfer invalid"); - _adjustTotalSupplyCheckpoints(); _mint(_investor, _value); emit Minted(_investor, _value); return true; @@ -692,7 +691,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater function _checkAndBurn(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); - _adjustTotalSupplyCheckpoints(); _burn(_from, _value); emit Burnt(_from, _value); return verified; @@ -709,7 +707,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater function _checkAndBurnFrom(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); - _adjustTotalSupplyCheckpoints(); _burnFrom(_from, _value); emit Burnt(_from, _value); return verified; @@ -735,6 +732,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /*solium-disable-next-line security/no-block-members*/ checkpointTimes.push(now); /*solium-disable-next-line security/no-block-members*/ + _adjustTotalSupplyCheckpoints(); emit CheckpointCreated(currentCheckpointId, now); return currentCheckpointId; } From ccf095682a66707d1ec180a9072db0f6f02b659d Mon Sep 17 00:00:00 2001 From: tft Date: Tue, 15 Jan 2019 16:41:30 +0530 Subject: [PATCH 064/119] Removed _adjustTotalSupplyCheckpoints & adjustCheckpoints as additional conditions were not needed and only one statement was happening in the function --- contracts/libraries/TokenLib.sol | 18 ------------------ contracts/tokens/SecurityToken.sol | 9 +-------- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 8585a3dba..2980392b0 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -222,24 +222,6 @@ library TokenLib { return _checkpoints[max].value; } - /** - * @notice Stores the changes to the checkpoint objects - * @param _checkpoints is the affected checkpoint object array - * @param _newValue is the new value that needs to be stored - */ - function adjustCheckpoints(TokenLib.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public { - //No checkpoints set yet - if (_currentCheckpointId == 0) { - return; - } - //No new checkpoints since last update - if ((_checkpoints.length > 0) && (_checkpoints[_checkpoints.length - 1].checkpointId == _currentCheckpointId)) { - return; - } - //New checkpoint, so record balance - _checkpoints.push(TokenLib.Checkpoint({checkpointId: _currentCheckpointId, value: _newValue})); - } - /** * @notice Keeps track of the number of non-zero token holders * @param _investorData Date releated to investor metrics diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 3168037b2..6082854a5 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -458,13 +458,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater emit FreezeTransfers(false, now); } - /** - * @notice Internal - adjusts totalSupply at checkpoint after minting or burning tokens - */ - function _adjustTotalSupplyCheckpoints() internal { - TokenLib.adjustCheckpoints(checkpointTotalSupply, totalSupply(), currentCheckpointId); - } - /** * @notice Internal - adjusts token holder balance at checkpoint after a token transfer * @param _investor address of the token holder affected @@ -732,7 +725,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /*solium-disable-next-line security/no-block-members*/ checkpointTimes.push(now); /*solium-disable-next-line security/no-block-members*/ - _adjustTotalSupplyCheckpoints(); + checkpointTotalSupply.push(TokenLib.Checkpoint({checkpointId: currentCheckpointId, value: totalSupply()})); emit CheckpointCreated(currentCheckpointId, now); return currentCheckpointId; } From 617a28871f9b9da3530f523df895bba7a3e711b1 Mon Sep 17 00:00:00 2001 From: tft Date: Tue, 15 Jan 2019 18:57:03 +0530 Subject: [PATCH 065/119] Reinstated the function adjustCheckpoints --- contracts/libraries/TokenLib.sol | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 2980392b0..8585a3dba 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -222,6 +222,24 @@ library TokenLib { return _checkpoints[max].value; } + /** + * @notice Stores the changes to the checkpoint objects + * @param _checkpoints is the affected checkpoint object array + * @param _newValue is the new value that needs to be stored + */ + function adjustCheckpoints(TokenLib.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public { + //No checkpoints set yet + if (_currentCheckpointId == 0) { + return; + } + //No new checkpoints since last update + if ((_checkpoints.length > 0) && (_checkpoints[_checkpoints.length - 1].checkpointId == _currentCheckpointId)) { + return; + } + //New checkpoint, so record balance + _checkpoints.push(TokenLib.Checkpoint({checkpointId: _currentCheckpointId, value: _newValue})); + } + /** * @notice Keeps track of the number of non-zero token holders * @param _investorData Date releated to investor metrics From 1e05bbd94ae74fc12fd6856ac622789ef5454368 Mon Sep 17 00:00:00 2001 From: tft Date: Tue, 15 Jan 2019 20:20:08 +0530 Subject: [PATCH 066/119] Changed data-type of checkpointTotalSupply from struct to mapping as it will save gas and will do the work --- contracts/tokens/SecurityToken.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 6082854a5..505a403ee 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -76,8 +76,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Map each investor to a series of checkpoints mapping(address => TokenLib.Checkpoint[]) checkpointBalances; - // List of checkpoints that relate to total supply - TokenLib.Checkpoint[] checkpointTotalSupply; + // Mapping of checkpoints that relate to total supply + mapping (uint256 => uint256) checkpointTotalSupply; // Times at which each checkpoint was created uint256[] checkpointTimes; @@ -725,7 +725,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /*solium-disable-next-line security/no-block-members*/ checkpointTimes.push(now); /*solium-disable-next-line security/no-block-members*/ - checkpointTotalSupply.push(TokenLib.Checkpoint({checkpointId: currentCheckpointId, value: totalSupply()})); + checkpointTotalSupply[currentCheckpointId] = totalSupply(); emit CheckpointCreated(currentCheckpointId, now); return currentCheckpointId; } @@ -745,7 +745,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function totalSupplyAt(uint256 _checkpointId) external view returns(uint256) { require(_checkpointId <= currentCheckpointId); - return TokenLib.getValueAt(checkpointTotalSupply, _checkpointId, totalSupply()); + return checkpointTotalSupply[_checkpointId]; } /** From bfeab5833cf295780f31283a2c4d7c38ca5971f1 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 15 Jan 2019 21:06:01 +0530 Subject: [PATCH 067/119] 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 f44a7af89..8396cb5a3 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -93,7 +93,7 @@ if [ "$COVERAGE" = true ]; then curl -o node_modules/solidity-parser-sc/build/parser.js https://raw.githubusercontent.com/maxsam4/solidity-parser/solidity-0.5/build/parser.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 @@ -110,4 +110,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 6b2bb547d76adb7d295ffad29873089c67f483ba Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 18 Jan 2019 13:43:37 +0530 Subject: [PATCH 068/119] Added batch functions --- contracts/datastore/DataStore.sol | 267 ++++++++++++++++++----- contracts/datastore/DataStoreStorage.sol | 3 +- contracts/proxy/DataStoreProxy.sol | 2 +- 3 files changed, 216 insertions(+), 56 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 9d3ebabb3..841d9a8ef 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -5,111 +5,182 @@ import "../interfaces/IOwnable.sol"; import "./DataStoreStorage.sol"; contract DataStore is DataStoreStorage { + //Delegate with MANAGEDATA permission can modify data. + + modifier onlyAuthorized() { + bool isOwner = msg.sender == IOwnable(address(securityToken)).owner(); + require(isOwner || + securityToken.isModule(msg.sender, DATA_KEY) || + securityToken.checkPermission(msg.sender, address(this), MANAGEDATA), + "Unauthorized" + ); + _; + } - modifier onlyDataModuleWithValidKey(bytes32 _key) { + modifier validKey(bytes32 _key) { require(_key != bytes32(0), "Missing key"); - require(associatedToken.isModule(msg.sender, DATA_KEY), "Unauthorized"); + _; + } + + modifier validInputLength(uint256 _keyLength, uint256 _dataLength) { + require(_keyLength == _dataLength, "Array length mismatch"); _; } modifier onlyOwner() { - require(msg.sender == IOwnable(address(associatedToken)).owner(), "Unauthorized"); + require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); _; } function setSecurityToken(address _securityToken) public { - if(address(associatedToken) != address(0)) { - require(msg.sender == IOwnable(address(associatedToken)).owner(), "Unauthorized"); + if(address(securityToken) != address(0)) { + require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); } - associatedToken = ISecurityToken(_securityToken); + securityToken = ISecurityToken(_securityToken); } - function setData(bytes32 _key, uint256 _data) external onlyDataModuleWithValidKey(_key) { - uintData[_key] = _data; + function setData(bytes32 _key, uint256 _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, bytes32 _data) external onlyDataModuleWithValidKey(_key) { - bytes32Data[_key] = _data; + function setData(bytes32 _key, bytes32 _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, address _data) external onlyDataModuleWithValidKey(_key) { - addressData[_key] = _data; + function setData(bytes32 _key, address _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, string calldata _data) external onlyDataModuleWithValidKey(_key) { - stringData[_key] = _data; + function setData(bytes32 _key, string calldata _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, bytes calldata _data) external onlyDataModuleWithValidKey(_key) { - bytesData[_key] = _data; + function setData(bytes32 _key, bytes calldata _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, bool _data) external onlyDataModuleWithValidKey(_key) { - boolData[_key] = _data; + function setData(bytes32 _key, bool _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, uint256[] calldata _data) external onlyDataModuleWithValidKey(_key) { - uintArrayData[_key] = _data; + function setData(bytes32 _key, uint256[] calldata _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, bytes32[] calldata _data) external onlyDataModuleWithValidKey(_key) { - bytes32ArrayData[_key] = _data; + function setData(bytes32 _key, bytes32[] calldata _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, address[] calldata _data) external onlyDataModuleWithValidKey(_key) { - addressArrayData[_key] = _data; + function setData(bytes32 _key, address[] calldata _data) external onlyAuthorized { + _setData(_key, _data); } - function setData(bytes32 _key, bool[] calldata _data) external onlyDataModuleWithValidKey(_key) { - boolArrayData[_key] = _data; + function setData(bytes32 _key, bool[] calldata _data) external onlyAuthorized { + _setData(_key, _data); } - function insertData(bytes32 _key, uint256 _data) external onlyDataModuleWithValidKey(_key) { - uintArrayData[_key].push(_data); + function insertData(bytes32 _key, uint256 _data) external onlyAuthorized { + _insertData(_key, _data); } - function insertData(bytes32 _key, bytes32 _data) external onlyDataModuleWithValidKey(_key) { - bytes32ArrayData[_key].push(_data); + function insertData(bytes32 _key, bytes32 _data) external onlyAuthorized { + _insertData(_key, _data); } - function insertData(bytes32 _key, address _data) external onlyDataModuleWithValidKey(_key) { - addressArrayData[_key].push(_data); + function insertData(bytes32 _key, address _data) external onlyAuthorized { + _insertData(_key, _data); } - function insertData(bytes32 _key, bool _data) external onlyDataModuleWithValidKey(_key) { - boolArrayData[_key].push(_data); + function insertData(bytes32 _key, bool _data) external onlyAuthorized { + _insertData(_key, _data); } - function deleteUint(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { - require(uintArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(uintArrayData[_key].length - 1 != _index) { - uintArrayData[_key][_index] = uintArrayData[_key][uintArrayData[_key].length - 1]; + function deleteUint(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteUint(_key, _index); + } + + function deleteBytes32(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteBytes32(_key, _index); + } + + function deleteAddress(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteAddress(_key, _index); + } + + function deleteBool(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteBool(_key, _index); + } + + function setDataMulti(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); } - uintArrayData[_key].length--; } - function deleteBytes32(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { - require(bytes32ArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(bytes32ArrayData[_key].length - 1 != _index) { - bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][uintArrayData[_key].length - 1]; + function setDataMulti(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); } - bytes32ArrayData[_key].length--; } - function deleteAddress(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { - require(addressArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(addressArrayData[_key].length - 1 != _index) { - addressArrayData[_key][_index] = addressArrayData[_key][uintArrayData[_key].length - 1]; + function setDataMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); } - addressArrayData[_key].length--; } - function deleteBool(bytes32 _key, uint256 _index) external onlyDataModuleWithValidKey(_key) { - require(boolArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(boolArrayData[_key].length - 1 != _index) { - boolArrayData[_key][_index] = boolArrayData[_key][uintArrayData[_key].length - 1]; + function setDataMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); + } + } + + function insertDataMulti(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function insertDataMulti(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function insertDataMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function insertDataMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function deleteUintMulti(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _deleteUint(_keys[i], _indexes[i]); + } + } + + function deleteBytes32Multi(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _deleteBytes32(_keys[i], _indexes[i]); + } + } + + function deleteAddressMulti(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _deleteAddress(_keys[i], _indexes[i]); + } + } + + function deleteBoolMulti(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _deleteBool(_keys[i], _indexes[i]); } - boolArrayData[_key].length--; } function getUint(bytes32 _key) external view returns(uint256) { @@ -183,4 +254,92 @@ contract DataStore is DataStoreStorage { function getBoolArrayElement(bytes32 _key, uint256 _index) external view returns(bool) { return boolArrayData[_key][_index]; } + + function _setData(bytes32 _key, uint256 _data) internal validKey(_key) { + uintData[_key] = _data; + } + + function _setData(bytes32 _key, bytes32 _data) internal validKey(_key) { + bytes32Data[_key] = _data; + } + + function _setData(bytes32 _key, address _data) internal validKey(_key) { + addressData[_key] = _data; + } + + function _setData(bytes32 _key, string memory _data) internal validKey(_key) { + stringData[_key] = _data; + } + + function _setData(bytes32 _key, bytes memory _data) internal validKey(_key) { + bytesData[_key] = _data; + } + + function _setData(bytes32 _key, bool _data) internal validKey(_key) { + boolData[_key] = _data; + } + + function _setData(bytes32 _key, uint256[] memory _data) internal validKey(_key) { + uintArrayData[_key] = _data; + } + + function _setData(bytes32 _key, bytes32[] memory _data) internal validKey(_key) { + bytes32ArrayData[_key] = _data; + } + + function _setData(bytes32 _key, address[] memory _data) internal validKey(_key) { + addressArrayData[_key] = _data; + } + + function _setData(bytes32 _key, bool[] memory _data) internal validKey(_key) { + boolArrayData[_key] = _data; + } + + function _insertData(bytes32 _key, uint256 _data) internal validKey(_key) { + uintArrayData[_key].push(_data); + } + + function _insertData(bytes32 _key, bytes32 _data) internal validKey(_key) { + bytes32ArrayData[_key].push(_data); + } + + function _insertData(bytes32 _key, address _data) internal validKey(_key) { + addressArrayData[_key].push(_data); + } + + function _insertData(bytes32 _key, bool _data) internal validKey(_key) { + boolArrayData[_key].push(_data); + } + + function _deleteUint(bytes32 _key, uint256 _index) internal validKey(_key) { + require(uintArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(uintArrayData[_key].length - 1 != _index) { + uintArrayData[_key][_index] = uintArrayData[_key][uintArrayData[_key].length - 1]; + } + uintArrayData[_key].length--; + } + + function _deleteBytes32(bytes32 _key, uint256 _index) internal validKey(_key) { + require(bytes32ArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(bytes32ArrayData[_key].length - 1 != _index) { + bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][uintArrayData[_key].length - 1]; + } + bytes32ArrayData[_key].length--; + } + + function _deleteAddress(bytes32 _key, uint256 _index) internal validKey(_key) { + require(addressArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(addressArrayData[_key].length - 1 != _index) { + addressArrayData[_key][_index] = addressArrayData[_key][uintArrayData[_key].length - 1]; + } + addressArrayData[_key].length--; + } + + function _deleteBool(bytes32 _key, uint256 _index) internal validKey(_key) { + require(boolArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(boolArrayData[_key].length - 1 != _index) { + boolArrayData[_key][_index] = boolArrayData[_key][uintArrayData[_key].length - 1]; + } + boolArrayData[_key].length--; + } } diff --git a/contracts/datastore/DataStoreStorage.sol b/contracts/datastore/DataStoreStorage.sol index 2dba41ede..dd869ce20 100644 --- a/contracts/datastore/DataStoreStorage.sol +++ b/contracts/datastore/DataStoreStorage.sol @@ -3,7 +3,7 @@ pragma solidity ^0.5.0; import "../interfaces/ISecurityToken.sol"; contract DataStoreStorage { - ISecurityToken public associatedToken; + ISecurityToken public securityToken; mapping (bytes32 => uint256) internal uintData; mapping (bytes32 => bytes32) internal bytes32Data; @@ -17,4 +17,5 @@ contract DataStoreStorage { mapping (bytes32 => bool[]) internal boolArrayData; uint8 constant DATA_KEY = 10; + bytes32 public constant MANAGEDATA = "MANAGEDATA"; } diff --git a/contracts/proxy/DataStoreProxy.sol b/contracts/proxy/DataStoreProxy.sol index 6d2ce2482..b79f5579d 100644 --- a/contracts/proxy/DataStoreProxy.sol +++ b/contracts/proxy/DataStoreProxy.sol @@ -22,7 +22,7 @@ contract DataStoreProxy is DataStoreStorage, OwnedProxy { require(_implementation != address(0) && _securityToken != address(0), "Address should not be 0x" ); - associatedToken = ISecurityToken(_securityToken); + securityToken = ISecurityToken(_securityToken); __implementation = _implementation; } From 602dc051f9b830efa2a4d6c6a48bcbf177a41617 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 18 Jan 2019 13:53:15 +0530 Subject: [PATCH 069/119] Removed multi delete --- contracts/datastore/DataStore.sol | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 841d9a8ef..50d9c87a0 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -32,7 +32,7 @@ contract DataStore is DataStoreStorage { _; } - function setSecurityToken(address _securityToken) public { + function setSecurityToken(address _securityToken) public onlyOwner { if(address(securityToken) != address(0)) { require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); } @@ -159,30 +159,6 @@ contract DataStore is DataStoreStorage { } } - function deleteUintMulti(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { - for (uint256 i = 0; i < _keys.length; i++) { - _deleteUint(_keys[i], _indexes[i]); - } - } - - function deleteBytes32Multi(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { - for (uint256 i = 0; i < _keys.length; i++) { - _deleteBytes32(_keys[i], _indexes[i]); - } - } - - function deleteAddressMulti(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { - for (uint256 i = 0; i < _keys.length; i++) { - _deleteAddress(_keys[i], _indexes[i]); - } - } - - function deleteBoolMulti(bytes32[] calldata _keys, uint256[] calldata _indexes) external onlyAuthorized validInputLength(_keys.length, _indexes.length) { - for (uint256 i = 0; i < _keys.length; i++) { - _deleteBool(_keys[i], _indexes[i]); - } - } - function getUint(bytes32 _key) external view returns(uint256) { return uintData[_key]; } From 1b16ad4b3ad9614ab1fd691c51d079ba7ceb42eb Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 22 Jan 2019 11:59:28 +0530 Subject: [PATCH 070/119] Removed overloaded external functions --- contracts/datastore/DataStore.sol | 62 ++++++++++--------- .../TransferManager/KYCTransferManager.sol | 12 ++-- contracts/tokens/SecurityToken.sol | 1 + 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 50d9c87a0..072a9e3c3 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -5,6 +5,8 @@ import "../interfaces/IOwnable.sol"; import "./DataStoreStorage.sol"; contract DataStore is DataStoreStorage { + //NB To modify a specific element of an array, First push a new element to the array and then delete the old element. + //Whenver an element is deleted from an Array, last element of that array is moved to the index of deleted element. //Delegate with MANAGEDATA permission can modify data. modifier onlyAuthorized() { @@ -39,63 +41,63 @@ contract DataStore is DataStoreStorage { securityToken = ISecurityToken(_securityToken); } - function setData(bytes32 _key, uint256 _data) external onlyAuthorized { + function setUint256(bytes32 _key, uint256 _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, bytes32 _data) external onlyAuthorized { + function setBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, address _data) external onlyAuthorized { + function setAddress(bytes32 _key, address _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, string calldata _data) external onlyAuthorized { + function setString(bytes32 _key, string calldata _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, bytes calldata _data) external onlyAuthorized { + function setBytes(bytes32 _key, bytes calldata _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, bool _data) external onlyAuthorized { + function setBool(bytes32 _key, bool _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, uint256[] calldata _data) external onlyAuthorized { + function setUint256Array(bytes32 _key, uint256[] calldata _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, bytes32[] calldata _data) external onlyAuthorized { + function setBytes32Array(bytes32 _key, bytes32[] calldata _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, address[] calldata _data) external onlyAuthorized { + function setAddressArray(bytes32 _key, address[] calldata _data) external onlyAuthorized { _setData(_key, _data); } - function setData(bytes32 _key, bool[] calldata _data) external onlyAuthorized { + function setBoolArray(bytes32 _key, bool[] calldata _data) external onlyAuthorized { _setData(_key, _data); } - function insertData(bytes32 _key, uint256 _data) external onlyAuthorized { + function insertUint256(bytes32 _key, uint256 _data) external onlyAuthorized { _insertData(_key, _data); } - function insertData(bytes32 _key, bytes32 _data) external onlyAuthorized { + function insertBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { _insertData(_key, _data); } - function insertData(bytes32 _key, address _data) external onlyAuthorized { + function insertAddress(bytes32 _key, address _data) external onlyAuthorized { _insertData(_key, _data); } - function insertData(bytes32 _key, bool _data) external onlyAuthorized { + function insertBool(bytes32 _key, bool _data) external onlyAuthorized { _insertData(_key, _data); } - function deleteUint(bytes32 _key, uint256 _index) external onlyAuthorized { + function deleteUint256(bytes32 _key, uint256 _index) external onlyAuthorized { _deleteUint(_key, _index); } @@ -111,55 +113,55 @@ contract DataStore is DataStoreStorage { _deleteBool(_key, _index); } - function setDataMulti(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function setDataMulti(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function setDataMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function setDataMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function insertDataMulti(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function insertDataMulti(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function insertDataMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function insertDataMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function getUint(bytes32 _key) external view returns(uint256) { + function getUint256(bytes32 _key) external view returns(uint256) { return uintData[_key]; } @@ -183,7 +185,7 @@ contract DataStore is DataStoreStorage { return boolData[_key]; } - function getUintArray(bytes32 _key) external view returns(uint256[] memory) { + function getUint256Array(bytes32 _key) external view returns(uint256[] memory) { return uintArrayData[_key]; } @@ -199,7 +201,7 @@ contract DataStore is DataStoreStorage { return boolArrayData[_key]; } - function getUintArrayLength(bytes32 _key) external view returns(uint256) { + function getUint256ArrayLength(bytes32 _key) external view returns(uint256) { return uintArrayData[_key].length; } @@ -215,7 +217,7 @@ contract DataStore is DataStoreStorage { return boolArrayData[_key].length; } - function getUintArrayElement(bytes32 _key, uint256 _index) external view returns(uint256) { + function getUint256ArrayElement(bytes32 _key, uint256 _index) external view returns(uint256) { return uintArrayData[_key][_index]; } @@ -298,7 +300,7 @@ contract DataStore is DataStoreStorage { function _deleteBytes32(bytes32 _key, uint256 _index) internal validKey(_key) { require(bytes32ArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow if(bytes32ArrayData[_key].length - 1 != _index) { - bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][uintArrayData[_key].length - 1]; + bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][bytes32ArrayData[_key].length - 1]; } bytes32ArrayData[_key].length--; } @@ -306,7 +308,7 @@ contract DataStore is DataStoreStorage { function _deleteAddress(bytes32 _key, uint256 _index) internal validKey(_key) { require(addressArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow if(addressArrayData[_key].length - 1 != _index) { - addressArrayData[_key][_index] = addressArrayData[_key][uintArrayData[_key].length - 1]; + addressArrayData[_key][_index] = addressArrayData[_key][addressArrayData[_key].length - 1]; } addressArrayData[_key].length--; } @@ -314,7 +316,7 @@ contract DataStore is DataStoreStorage { function _deleteBool(bytes32 _key, uint256 _index) internal validKey(_key) { require(boolArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow if(boolArrayData[_key].length - 1 != _index) { - boolArrayData[_key][_index] = boolArrayData[_key][uintArrayData[_key].length - 1]; + boolArrayData[_key][_index] = boolArrayData[_key][boolArrayData[_key].length - 1]; } boolArrayData[_key].length--; } diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol index 9c6d8ddd3..a48c20fa1 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -43,7 +43,7 @@ contract KYCTransferManager is TransferManager { if (!paused) { bytes32 key = _getKYCKey(_to); DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); - if (dataStore.getUint(key) > 0) + if (dataStore.getUint256(key) > 0) return Result.VALID; } return Result.NA; @@ -56,19 +56,19 @@ contract KYCTransferManager is TransferManager { function _modifyKYC(address _investor, bool _kycStatus) internal { DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); bytes32 key = _getKYCKey(_investor); - uint256 kycNumber = dataStore.getUint(key); //index in address array + 1 + uint256 kycNumber = dataStore.getUint256(key); //index in address array + 1 uint256 kycTotal = dataStore.getAddressArrayLength(KYC_ARRAY); if(_kycStatus) { require(kycNumber == 0, "KYC exists"); - dataStore.setData(key, kycTotal + 1); - dataStore.insertData(KYC_ARRAY, _investor); + dataStore.setUint256(key, kycTotal + 1); + dataStore.insertAddress(KYC_ARRAY, _investor); } else { require(kycNumber != 0, "KYC does not exist"); address lastAddress = dataStore.getAddressArrayElement(KYC_ARRAY, kycTotal - 1); dataStore.deleteAddress(KYC_ARRAY, kycNumber - 1); //Corrects the index of last element as delete fucntions move last element to index. - dataStore.setData(_getKYCKey(lastAddress), kycNumber); + dataStore.setUint256(_getKYCKey(lastAddress), kycNumber); } //Alternatively, we can just emit an event and not maintain the KYC array on chain. //I am maintaining the array to showcase how it can be done in cases where it might be needed. @@ -91,7 +91,7 @@ contract KYCTransferManager is TransferManager { function checkKYC(address _investor) public view returns (bool kyc) { bytes32 key = _getKYCKey(_investor); DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); - if (dataStore.getUint(key) > 0) + if (dataStore.getUint256(key) > 0) kyc = true; } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 1adce5bac..80e5abb0f 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -65,6 +65,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Address whitelisted by issuer as controller address public controller; + // Address of the data store used to store shared data address public dataStore; // Records added modules - module list should be order agnostic! From 82a99c15a193cf41404121d231bf16f73bbaea19 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 22 Jan 2019 11:59:41 +0530 Subject: [PATCH 071/119] Added test cases --- test/za_datastore.js | 349 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 294 insertions(+), 55 deletions(-) diff --git a/test/za_datastore.js b/test/za_datastore.js index 9b590e78f..e6cab2318 100644 --- a/test/za_datastore.js +++ b/test/za_datastore.js @@ -1,121 +1,360 @@ +import latestTime from "./helpers/latestTime"; +import { catchRevert } from "./helpers/exceptions"; +import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; +import { setUpPolymathNetwork } from "./helpers/createInstances"; +const SecurityToken = artifacts.require("./SecurityToken.sol"); +const DataStore = artifacts.require("./DataStore.sol"); + const Web3 = require("web3"); let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port contract("Data store", async (accounts) => { - describe("Should attach to security token securely", async () => { - it("Should be attached to a security token upon deployment", async () => { - - }); + // Accounts Variable declaration + let account_polymath; + let token_owner; - it("Should not allow non-issuer to change security token address", async () => { - + // Contract Instance Declaration + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + let I_DataStore; + let I_ModuleRegistryProxy; + let I_MRProxied; + let I_STRGetter; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const contact = "team@polymath.network"; + const key = "0x41"; + const bytes32data = "0x4200000000000000000000000000000000000000000000000000000000000000"; + const bytes32data2 = "0x4400000000000000000000000000000000000000000000000000000000000000"; + + // Initial fee for ticker registry and security token registry + const initRegFee = new BN(web3.utils.toWei("250")); + + const address_zero = "0x0000000000000000000000000000000000000000"; + const address_one = "0x0000000000000000000000000000000000000001"; + + before(async () => { + account_polymath = accounts[0]; + token_owner = accounts[1]; + + // 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, + I_STRGetter + ] = instances; + + + + // 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} + 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 not allow DATA module to change security token address", async () => { - + 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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', { filter: { transactionHash: tx.transactionHash } }))[0]; + + // 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 allow issuer to change security token address", async () => { - + it("Should fetch data store address", async () => { + I_DataStore = await DataStore.at(await I_SecurityToken.dataStore()); }); }); - describe("Should not allow unautohrized modification to data", async () => { - it("Should not allow random addresses to modify data", async () => { - + describe("Should attach to security token securely", async () => { + it("Should be attached to a security token upon deployment", async () => { + assert.equal(await I_DataStore.securityToken(), I_SecurityToken.address, "Incorrect Security Token attached"); }); - it("Should not allow modules that does not belong to DATA type to modify data", async () => { - + it("Should not allow non-issuer to change security token address", async () => { + await catchRevert(I_DataStore.setSecurityToken(address_one, { from: account_polymath })); }); - it("Should not allow archived modules to modify data", async () => { - + it("Should allow issuer to change security token address", async () => { + let snapId = await takeSnapshot(); + await I_DataStore.setSecurityToken(address_one, { from: token_owner }); + assert.equal(await I_DataStore.securityToken(), address_one, "Incorrect Security Token attached"); + await revertToSnapshot(snapId); + assert.equal(await I_DataStore.securityToken(), I_SecurityToken.address, "Incorrect Security Token attached"); }); }); describe("Should set data correctly", async () => { - it("Should set uint256 correctly", async () => { + it("Should set and fetch uint256 correctly", async () => { + await I_DataStore.setUint256(key, 1, { from: token_owner }); + assert.equal((await I_DataStore.getUint256(key)).toNumber(), 1, "Incorrect Data Inserted"); + }); + + it("Should set and fetch bytes32 correctly", async () => { + await I_DataStore.setBytes32(key, bytes32data, { from: token_owner }); + assert.equal(await I_DataStore.getBytes32(key), bytes32data, "Incorrect Data Inserted"); + }); + + it("Should set and fetch address correctly", async () => { + await I_DataStore.setAddress(key, address_one, { from: token_owner }); + assert.equal(await I_DataStore.getAddress(key), address_one, "Incorrect Data Inserted"); + }); + + it("Should set and fetch string correctly", async () => { + await I_DataStore.setString(key, name, { from: token_owner }); + assert.equal(await I_DataStore.getString(key), name, "Incorrect Data Inserted"); + }); + + it("Should set and fetch bytes correctly", async () => { + await I_DataStore.setBytes(key, bytes32data, { from: token_owner }); + assert.equal(await I_DataStore.getBytes(key), bytes32data, "Incorrect Data Inserted"); + }); + + it("Should set and fetch bool correctly", async () => { + await I_DataStore.setBool(key, true, { from: token_owner }); + assert.equal(await I_DataStore.getBool(key), true, "Incorrect Data Inserted"); + }); + + it("Should set and fetch uint256 array correctly", async () => { + let arr = [1, 2]; + await I_DataStore.setUint256Array(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getUint256Array(key); + let arrLen = await I_DataStore.getUint256ArrayLength(key); + let arrElement2 = await I_DataStore.getUint256ArrayElement(key, 1); + assert.equal(arr2[0].toNumber(), arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1].toNumber(), arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2.toNumber(), arr[1], "Incorrect array element"); + }); + + it("Should set and fetch bytes32 array correctly", async () => { + let arr = [bytes32data, bytes32data2]; + await I_DataStore.setBytes32Array(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getBytes32Array(key); + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + let arrElement2 = await I_DataStore.getBytes32ArrayElement(key, 1); + assert.equal(arr2[0], arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1], arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2, arr[1], "Incorrect array element"); + }); + + it("Should set and fetch address array correctly", async () => { + let arr = [address_zero, address_one]; + await I_DataStore.setAddressArray(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getAddressArray(key); + let arrLen = await I_DataStore.getAddressArrayLength(key); + let arrElement2 = await I_DataStore.getAddressArrayElement(key, 1); + assert.equal(arr2[0], arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1], arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2, arr[1], "Incorrect array element"); + }); + + it("Should set and fetch bool array correctly", async () => { + let arr = [false, true]; + await I_DataStore.setBoolArray(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getBoolArray(key); + let arrLen = await I_DataStore.getBoolArrayLength(key); + let arrElement2 = await I_DataStore.getBoolArrayElement(key, 1); + assert.equal(arr2[0], arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1], arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2, arr[1], "Incorrect array element"); + }); + + it("Should insert uint256 into Array", async () => { + let arrLen = await I_DataStore.getUint256ArrayLength(key); + await I_DataStore.insertUint256(key, new BN(10), { from: token_owner }); + let arrElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement.toNumber(), 10, "Incorrect array element"); + }); + + it("Should insert bytes32 into Array", async () => { + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + await I_DataStore.insertBytes32(key, bytes32data, { from: token_owner }); + let arrElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, bytes32data, "Incorrect array element"); + }); + it("Should insert address into Array", async () => { + let arrLen = await I_DataStore.getAddressArrayLength(key); + await I_DataStore.insertAddress(key, address_one, { from: token_owner }); + let arrElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, address_one, "Incorrect array element"); }); - it("Should set bytes32 correctly", async () => { - + it("Should insert bool into Array", async () => { + let arrLen = await I_DataStore.getBoolArrayLength(key); + await I_DataStore.insertBool(key, true, { from: token_owner }); + let arrElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, true, "Incorrect array element"); }); - it("Should set address correctly", async () => { - + it("Should delete uint256 from Array", async () => { + let arrLen = await I_DataStore.getUint256ArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteUint256(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement.toNumber(), (await I_DataStore.getUint256ArrayElement(key, indexToDelete)).toNumber(), "Incorrect array element"); }); - it("Should set string correctly", async () => { - + it("Should delete bytes32 from Array", async () => { + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteBytes32(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement, await I_DataStore.getBytes32ArrayElement(key, indexToDelete), "Incorrect array element"); }); - it("Should set bytes correctly", async () => { - + it("Should delete address from Array", async () => { + let arrLen = await I_DataStore.getAddressArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteAddress(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement, await I_DataStore.getAddressArrayElement(key, indexToDelete), "Incorrect array element"); }); - it("Should set bool correctly", async () => { - + it("Should delete bool from Array", async () => { + let arrLen = await I_DataStore.getBoolArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteBool(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement, await I_DataStore.getBoolArrayElement(key, indexToDelete), "Incorrect array element"); }); + }); - it("Should set uint256 array correctly", async () => { + describe("Should not allow unautohrized modification to data", async () => { + it("Should not allow unauthorized addresses to modify uint256", async () => { + await catchRevert(I_DataStore.setUint256(key, new BN(1), { from: account_polymath })); + }); + it("Should not allow unauthorized addresses to modify bytes32", async () => { + await catchRevert(I_DataStore.setBytes32(key, bytes32data, { from: account_polymath })); }); - it("Should set bytes32 array correctly", async () => { - + it("Should not allow unauthorized addresses to modify address", async () => { + await catchRevert(I_DataStore.setAddress(key, address_one, { from: account_polymath })); }); - it("Should set address array correctly", async () => { - + it("Should not allow unauthorized addresses to modify string", async () => { + await catchRevert(I_DataStore.setString(key, name, { from: account_polymath })); }); - it("Should set bool array correctly", async () => { - + it("Should not allow unauthorized addresses to modify bytes", async () => { + await catchRevert(I_DataStore.setBytes32(key, bytes32data, { from: account_polymath })); }); - }); - describe("Should fetch data correctly", async () => { - it("Should fetch uint256 correctly", async () => { + it("Should not allow unauthorized addresses to modify bool", async () => { + await catchRevert(I_DataStore.setBool(key, true, { from: account_polymath })); + }); + it("Should not allow unauthorized addresses to modify uint256 array", async () => { + let arr = [1, 2]; + await catchRevert(I_DataStore.setUint256Array(key, arr, { from: account_polymath })); }); - it("Should fetch bytes32 correctly", async () => { - + it("Should not allow unauthorized addresses to modify bytes32 array", async () => { + let arr = [bytes32data, bytes32data2]; + await catchRevert(I_DataStore.setBytes32Array(key, arr, { from: account_polymath })); }); - it("Should fetch address correctly", async () => { - + it("Should not allow unauthorized addresses to modify address array", async () => { + let arr = [address_zero, address_one]; + await catchRevert(I_DataStore.setAddressArray(key, arr, { from: account_polymath })); }); - it("Should fetch string correctly", async () => { - + it("Should not allow unauthorized addresses to modify bool array", async () => { + let arr = [false, true]; + await catchRevert(I_DataStore.setBoolArray(key, arr, { from: account_polymath })); }); - it("Should fetch bytes correctly", async () => { - + it("Should not allow unauthorized addresses to insert uint256 into Array", async () => { + await catchRevert(I_DataStore.insertUint256(key, new BN(10), { from: account_polymath })); }); - it("Should fetch bool correctly", async () => { - + it("Should not allow unauthorized addresses to insert bytes32 into Array", async () => { + await catchRevert(I_DataStore.insertBytes32(key, bytes32data, { from: account_polymath })); }); - it("Should fetch uint256 array correctly", async () => { + it("Should not allow unauthorized addresses to insert address into Array", async () => { + await catchRevert(I_DataStore.insertAddress(key, address_one, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert bool into Array", async () => { + await catchRevert(I_DataStore.insertBool(key, true, { from: account_polymath })); + }); + it("Should not allow unauthorized addresses to delete uint256 from Array", async () => { + await catchRevert(I_DataStore.deleteUint256(key, 0, { from: account_polymath })); }); - it("Should fetch bytes32 array correctly", async () => { - + it("Should not allow unauthorized addresses to delete bytes32 from Array", async () => { + await catchRevert(I_DataStore.deleteBytes32(key, 0, { from: account_polymath })); }); - it("Should fetch address array correctly", async () => { - + it("Should not allow unauthorized addresses to delete address from Array", async () => { + await catchRevert(I_DataStore.deleteAddress(key, 0, { from: account_polymath })); }); - it("Should fetch bool array correctly", async () => { - + it("Should not allow unauthorized addresses to delete bool from Array", async () => { + await catchRevert(I_DataStore.deleteBool(key, 0, { from: account_polymath })); }); }); }); \ No newline at end of file From 2d24fe588de9b23c6ef656640abe9c89fdb82d16 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 23 Jan 2019 12:34:28 +0530 Subject: [PATCH 072/119] Code cleanup and comments --- contracts/datastore/DataStore.sol | 43 +++++- contracts/datastore/DataStoreStorage.sol | 2 +- contracts/interfaces/IDataStore.sol | 128 ++++++++++++++++++ contracts/interfaces/ISecurityToken.sol | 14 +- .../TransferManager/KYCTransferManager.sol | 10 +- contracts/tokens/STFactory.sol | 2 +- contracts/tokens/SecurityToken.sol | 18 ++- 7 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 contracts/interfaces/IDataStore.sol diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 072a9e3c3..29d2e2b1d 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -2,9 +2,13 @@ pragma solidity ^0.5.0; import "../interfaces/ISecurityToken.sol"; import "../interfaces/IOwnable.sol"; +import "../interfaces/IDataStore.sol"; import "./DataStoreStorage.sol"; -contract DataStore is DataStoreStorage { +/** + * @title Data store contract that stores data for all the modules in a central contract. + */ +contract DataStore is DataStoreStorage, IDataStore { //NB To modify a specific element of an array, First push a new element to the array and then delete the old element. //Whenver an element is deleted from an Array, last element of that array is moved to the index of deleted element. //Delegate with MANAGEDATA permission can modify data. @@ -34,13 +38,22 @@ contract DataStore is DataStoreStorage { _; } - function setSecurityToken(address _securityToken) public onlyOwner { + /** + * @dev Changes security token atatched to this data store + * @param _securityToken address of the security token + */ + function setSecurityToken(address _securityToken) external onlyOwner { if(address(securityToken) != address(0)) { require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); } securityToken = ISecurityToken(_securityToken); } + /** + * @dev Stores a uint256 data against a key + * @param _key Unique key to identify the data + * @param _data Data to be stored against the key + */ function setUint256(bytes32 _key, uint256 _data) external onlyAuthorized { _setData(_key, _data); } @@ -65,6 +78,11 @@ contract DataStore is DataStoreStorage { _setData(_key, _data); } + /** + * @dev Stores a uint256 array against a key + * @param _key Unique key to identify the array + * @param _data Array to be stored against the key + */ function setUint256Array(bytes32 _key, uint256[] calldata _data) external onlyAuthorized { _setData(_key, _data); } @@ -81,6 +99,11 @@ contract DataStore is DataStoreStorage { _setData(_key, _data); } + /** + * @dev Inserts a uint256 element to the array identified by the key + * @param _key Unique key to identify the array + * @param _data Element to push into the array + */ function insertUint256(bytes32 _key, uint256 _data) external onlyAuthorized { _insertData(_key, _data); } @@ -97,6 +120,12 @@ contract DataStore is DataStoreStorage { _insertData(_key, _data); } + /** + * @dev Deletes an element from the array identified by the key. + * When an element is deleted from an Array, last element of that array is moved to the index of deleted element. + * @param _key Unique key to identify the array + * @param _index Index of the element to delete + */ function deleteUint256(bytes32 _key, uint256 _index) external onlyAuthorized { _deleteUint(_key, _index); } @@ -113,6 +142,11 @@ contract DataStore is DataStoreStorage { _deleteBool(_key, _index); } + /** + * @dev Stores multiple uint256 data against respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be stored against the respective keys + */ function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); @@ -137,6 +171,11 @@ contract DataStore is DataStoreStorage { } } + /** + * @dev Inserts multiple uint256 elements to the array identified by the respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be inserted in arrays of the respective keys + */ function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); diff --git a/contracts/datastore/DataStoreStorage.sol b/contracts/datastore/DataStoreStorage.sol index dd869ce20..9d724f070 100644 --- a/contracts/datastore/DataStoreStorage.sol +++ b/contracts/datastore/DataStoreStorage.sol @@ -16,6 +16,6 @@ contract DataStoreStorage { mapping (bytes32 => address[]) internal addressArrayData; mapping (bytes32 => bool[]) internal boolArrayData; - uint8 constant DATA_KEY = 10; + uint8 constant DATA_KEY = 6; bytes32 public constant MANAGEDATA = "MANAGEDATA"; } diff --git a/contracts/interfaces/IDataStore.sol b/contracts/interfaces/IDataStore.sol new file mode 100644 index 000000000..bb1aa5aa4 --- /dev/null +++ b/contracts/interfaces/IDataStore.sol @@ -0,0 +1,128 @@ +pragma solidity ^0.5.0; + +interface IDataStore { + /** + * @dev Changes security token atatched to this data store + * @param _securityToken address of the security token + */ + function setSecurityToken(address _securityToken) external; + + /** + * @dev Stores a uint256 data against a key + * @param _key Unique key to identify the data + * @param _data Data to be stored against the key + */ + function setUint256(bytes32 _key, uint256 _data) external; + + function setBytes32(bytes32 _key, bytes32 _data) external; + + function setAddress(bytes32 _key, address _data) external; + + function setString(bytes32 _key, string calldata _data) external; + + function setBytes(bytes32 _key, bytes calldata _data) external; + + function setBool(bytes32 _key, bool _data) external; + + /** + * @dev Stores a uint256 array against a key + * @param _key Unique key to identify the array + * @param _data Array to be stored against the key + */ + function setUint256Array(bytes32 _key, uint256[] calldata _data) external; + + function setBytes32Array(bytes32 _key, bytes32[] calldata _data) external ; + + function setAddressArray(bytes32 _key, address[] calldata _data) external; + + function setBoolArray(bytes32 _key, bool[] calldata _data) external; + + /** + * @dev Inserts a uint256 element to the array identified by the key + * @param _key Unique key to identify the array + * @param _data Element to push into the array + */ + function insertUint256(bytes32 _key, uint256 _data) external; + + function insertBytes32(bytes32 _key, bytes32 _data) external; + + function insertAddress(bytes32 _key, address _data) external; + + function insertBool(bytes32 _key, bool _data) external; + + /** + * @dev Deletes an element from the array identified by the key. + * When an element is deleted from an Array, last element of that array is moved to the index of deleted element. + * @param _key Unique key to identify the array + * @param _index Index of the element to delete + */ + function deleteUint256(bytes32 _key, uint256 _index) external; + + function deleteBytes32(bytes32 _key, uint256 _index) external; + + function deleteAddress(bytes32 _key, uint256 _index) external; + + function deleteBool(bytes32 _key, uint256 _index) external; + + /** + * @dev Stores multiple uint256 data against respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be stored against the respective keys + */ + function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external; + + function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external; + + function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external; + + function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external; + + /** + * @dev Inserts multiple uint256 elements to the array identified by the respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be inserted in arrays of the respective keys + */ + function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external; + + function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external; + + function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external; + + function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external; + + function getUint256(bytes32 _key) external view returns(uint256); + + function getBytes32(bytes32 _key) external view returns(bytes32); + + function getAddress(bytes32 _key) external view returns(address); + + function getString(bytes32 _key) external view returns(string memory); + + function getBytes(bytes32 _key) external view returns(bytes memory); + + function getBool(bytes32 _key) external view returns(bool); + + function getUint256Array(bytes32 _key) external view returns(uint256[] memory); + + function getBytes32Array(bytes32 _key) external view returns(bytes32[] memory); + + function getAddressArray(bytes32 _key) external view returns(address[] memory); + + function getBoolArray(bytes32 _key) external view returns(bool[] memory); + + function getUint256ArrayLength(bytes32 _key) external view returns(uint256); + + function getBytes32ArrayLength(bytes32 _key) external view returns(uint256); + + function getAddressArrayLength(bytes32 _key) external view returns(uint256); + + function getBoolArrayLength(bytes32 _key) external view returns(uint256); + + function getUint256ArrayElement(bytes32 _key, uint256 _index) external view returns(uint256); + + function getBytes32ArrayElement(bytes32 _key, uint256 _index) external view returns(bytes32); + + function getAddressArrayElement(bytes32 _key, uint256 _index) external view returns(address); + + function getBoolArrayElement(bytes32 _key, uint256 _index) external view returns(bool); +} diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index e1a0f104e..c1671db53 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -17,8 +17,6 @@ interface ISecurityToken { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); - function dataStore() external view returns (address); - /** * @notice Validates a transfer with a TransferManager module if it exists * @dev TransferManager module has a key of 2 @@ -163,6 +161,18 @@ interface ISecurityToken { */ function currentCheckpointId() external view returns(uint256); + /** + * @notice Gets data store address + * @return data store address + */ + function dataStore() external view returns (address); + + /** + * @notice Allows owner to change data store + * @param _dataStore Address of the token data store + */ + function changeDataStore(address _dataStore) external; + /** * @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. diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol index a48c20fa1..f43a9cd64 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.0; import "../../TransferManager/TransferManager.sol"; -import "../../../datastore/DataStore.sol"; +import "../../../interfaces/IDataStore.sol"; import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -42,7 +42,7 @@ contract KYCTransferManager is TransferManager { { if (!paused) { bytes32 key = _getKYCKey(_to); - DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); if (dataStore.getUint256(key) > 0) return Result.VALID; } @@ -54,7 +54,7 @@ contract KYCTransferManager is TransferManager { } function _modifyKYC(address _investor, bool _kycStatus) internal { - DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); bytes32 key = _getKYCKey(_investor); uint256 kycNumber = dataStore.getUint256(key); //index in address array + 1 uint256 kycTotal = dataStore.getAddressArrayLength(KYC_ARRAY); @@ -84,13 +84,13 @@ contract KYCTransferManager is TransferManager { } function getKYCAddresses() public view returns(address[] memory) { - DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); return dataStore.getAddressArray(KYC_ARRAY); } function checkKYC(address _investor) public view returns (bool kyc) { bytes32 key = _getKYCKey(_investor); - DataStore dataStore = DataStore(ISecurityToken(securityToken).dataStore()); + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); if (dataStore.getUint256(key) > 0) kyc = true; } diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index 5528d533a..d00e7e192 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -41,7 +41,7 @@ contract STFactory is ISTFactory { _polymathRegistry ); newSecurityToken.addModule(transferManagerFactory, "", 0, 0); - newSecurityToken.setDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); + newSecurityToken.changeDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); newSecurityToken.transferOwnership(_issuer); return address(newSecurityToken); } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 80e5abb0f..7a0cb0d5e 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -46,7 +46,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint8 constant MINT_KEY = 3; uint8 constant CHECKPOINT_KEY = 4; uint8 constant BURN_KEY = 5; - uint8 constant DATA_KEY = 10; + uint8 constant DATA_KEY = 6; uint256 public granularity; @@ -211,12 +211,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater securityTokenVersion = SemanticVersion(2, 0, 0); } - function setDataStore(address _dataStore) public { - require(_dataStore != address(0), "Invalid address"); - dataStore = _dataStore; - } - - /** + /** * @notice Attachs a module to the SecurityToken * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it * @dev to control restrictions on transfers. @@ -377,6 +372,15 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater granularity = _granularity; } + /** + * @notice Allows owner to change data store + * @param _dataStore Address of the token data store + */ + function changeDataStore(address _dataStore) public onlyOwner { + require(_dataStore != address(0), "Invalid address"); + dataStore = _dataStore; + } + /** * @notice Keeps track of the number of non-zero token holders * @param _from sender of transfer From bc882153062fd550779e6c270eb10e129fed92d7 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 23 Jan 2019 12:41:31 +0530 Subject: [PATCH 073/119] Added test cases for security token --- contracts/tokens/SecurityToken.sol | 2 +- test/o_security_token.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 7a0cb0d5e..1eb1acd65 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -376,7 +376,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @notice Allows owner to change data store * @param _dataStore Address of the token data store */ - function changeDataStore(address _dataStore) public onlyOwner { + function changeDataStore(address _dataStore) external onlyOwner { require(_dataStore != address(0), "Invalid address"); dataStore = _dataStore; } diff --git a/test/o_security_token.js b/test/o_security_token.js index aac62b9e0..fe51ca271 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -591,7 +591,7 @@ contract("SecurityToken", async (accounts) => { await catchRevert(I_SecurityToken.transfer(accounts[7], new BN(10).pow(new BN(17)), { from: account_investor1 })); }); - it("Should adjust granularity", async () => { + it("Should not allow 0 granularity", async () => { await catchRevert(I_SecurityToken.changeGranularity(0, { from: token_owner })); }); @@ -601,6 +601,21 @@ contract("SecurityToken", async (accounts) => { await I_SecurityToken.transfer(account_investor1, new BN(10).pow(new BN(17)), { from: accounts[7], gas: 2500000 }); }); + it("Should not allow unauthorized address to change data store", async () => { + await catchRevert(I_SecurityToken.changeDataStore(one_address, { from: account_polymath })); + }); + + it("Should not allow 0x0 address as data store", async () => { + await catchRevert(I_SecurityToken.changeDataStore(address_zero, { from: token_owner })); + }); + + it("Should change data store", async () => { + let ds = await I_SecurityToken.dataStore(); + await I_SecurityToken.changeDataStore(one_address, { from: token_owner }); + assert.equal(one_address, await I_SecurityToken.dataStore()); + I_SecurityToken.changeDataStore(ds, { from: token_owner }); + }); + 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], new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1, gas: 2500000 }); From cda7408eb7059248c93ec7bba131137132598480 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 23 Jan 2019 13:03:51 +0530 Subject: [PATCH 074/119] Added more test cases for data store --- test/o_security_token.js | 2 +- test/za_datastore.js | 108 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/test/o_security_token.js b/test/o_security_token.js index fe51ca271..d6adbbc99 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -613,7 +613,7 @@ contract("SecurityToken", async (accounts) => { let ds = await I_SecurityToken.dataStore(); await I_SecurityToken.changeDataStore(one_address, { from: token_owner }); assert.equal(one_address, await I_SecurityToken.dataStore()); - I_SecurityToken.changeDataStore(ds, { from: token_owner }); + await I_SecurityToken.changeDataStore(ds, { from: token_owner }); }); it("Should transfer from whitelist investor to non-whitelist investor in first tx and in 2nd tx non-whitelist to non-whitelist transfer", async () => { diff --git a/test/za_datastore.js b/test/za_datastore.js index e6cab2318..b89646bac 100644 --- a/test/za_datastore.js +++ b/test/za_datastore.js @@ -36,6 +36,7 @@ contract("Data store", async (accounts) => { const tokenDetails = "This is equity type of issuance"; const contact = "team@polymath.network"; const key = "0x41"; + const key2 = "0x42"; const bytes32data = "0x4200000000000000000000000000000000000000000000000000000000000000"; const bytes32data2 = "0x4400000000000000000000000000000000000000000000000000000000000000"; @@ -44,6 +45,7 @@ contract("Data store", async (accounts) => { const address_zero = "0x0000000000000000000000000000000000000000"; const address_one = "0x0000000000000000000000000000000000000001"; + const address_two = "0x0000000000000000000000000000000000000002"; before(async () => { account_polymath = accounts[0]; @@ -134,6 +136,7 @@ contract("Data store", async (accounts) => { describe("Should set data correctly", async () => { it("Should set and fetch uint256 correctly", async () => { + await catchRevert(I_DataStore.setUint256("0x0", 1, { from: token_owner })); await I_DataStore.setUint256(key, 1, { from: token_owner }); assert.equal((await I_DataStore.getUint256(key)).toNumber(), 1, "Incorrect Data Inserted"); }); @@ -278,6 +281,79 @@ contract("Data store", async (accounts) => { assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); assert.equal(lastElement, await I_DataStore.getBoolArrayElement(key, indexToDelete), "Incorrect array element"); }); + + it("Should set and fetch multiple uint256 correctly", async () => { + await catchRevert(I_DataStore.setUint256Multi([key], [1,2], { from: token_owner })); + await I_DataStore.setUint256Multi([key, key2], [1,2], { from: token_owner }); + assert.equal((await I_DataStore.getUint256(key)).toNumber(), 1, "Incorrect Data Inserted"); + assert.equal((await I_DataStore.getUint256(key2)).toNumber(), 2, "Incorrect Data Inserted"); + }); + + it("Should set and fetch multiple bytes32 correctly", async () => { + await I_DataStore.setBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: token_owner }); + assert.equal(await I_DataStore.getBytes32(key), bytes32data, "Incorrect Data Inserted"); + assert.equal(await I_DataStore.getBytes32(key2), bytes32data2, "Incorrect Data Inserted"); + }); + + it("Should set and fetch multiple address correctly", async () => { + await I_DataStore.setAddressMulti([key, key2], [address_one, address_two], { from: token_owner }); + assert.equal(await I_DataStore.getAddress(key), address_one, "Incorrect Data Inserted"); + assert.equal(await I_DataStore.getAddress(key2), address_two, "Incorrect Data Inserted"); + }); + + it("Should set and fetch multiple bool correctly", async () => { + await I_DataStore.setBoolMulti([key, key2], [true, true], { from: token_owner }); + assert.equal(await I_DataStore.getBool(key), true, "Incorrect Data Inserted"); + assert.equal(await I_DataStore.getBool(key2), true, "Incorrect Data Inserted"); + }); + + it("Should insert multiple uint256 into multiple Array", async () => { + let arrLen = await I_DataStore.getUint256ArrayLength(key); + let arrLen2 = await I_DataStore.getUint256ArrayLength(key2); + await I_DataStore.insertUint256Multi([key, key2], [10, 20], { from: token_owner }); + let arrElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getUint256ArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement.toNumber(), 10, "Incorrect array element"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement2.toNumber(), 20, "Incorrect array element"); + }); + + it("Should insert multiple bytes32 into multiple Array", async () => { + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + let arrLen2 = await I_DataStore.getBytes32ArrayLength(key2); + await I_DataStore.insertBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: token_owner }); + let arrElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getBytes32ArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, bytes32data, "Incorrect array element"); + assert.equal(arrElement2, bytes32data2, "Incorrect array element"); + }); + + it("Should insert multiple address into multiple Array", async () => { + let arrLen = await I_DataStore.getAddressArrayLength(key); + let arrLen2 = await I_DataStore.getAddressArrayLength(key2); + await I_DataStore.insertAddressMulti([key, key2], [address_one, address_two], { from: token_owner }); + let arrElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getAddressArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, address_one, "Incorrect array element"); + assert.equal(arrElement2, address_two, "Incorrect array element"); + }); + + it("Should insert multiple bool into multiple Array", async () => { + let arrLen = await I_DataStore.getBoolArrayLength(key); + let arrLen2 = await I_DataStore.getBoolArrayLength(key2); + await I_DataStore.insertBoolMulti([key, key2], [true, true], { from: token_owner }); + let arrElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getBoolArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, true, "Incorrect array element"); + assert.equal(arrElement2, true, "Incorrect array element"); + }); }); describe("Should not allow unautohrized modification to data", async () => { @@ -356,5 +432,37 @@ contract("Data store", async (accounts) => { it("Should not allow unauthorized addresses to delete bool from Array", async () => { await catchRevert(I_DataStore.deleteBool(key, 0, { from: account_polymath })); }); + + it("Should not allow unauthorized addresses to modify multiple uint256", async () => { + await catchRevert(I_DataStore.setUint256Multi([key, key2], [1,2], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple bytes32", async () => { + await catchRevert(I_DataStore.setBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple address", async () => { + await catchRevert(I_DataStore.setAddressMulti([key, key2], [address_one, address_two], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple bool", async () => { + await catchRevert(I_DataStore.setBoolMulti([key, key2], [true, true], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple uint256 into multiple Array", async () => { + await catchRevert(I_DataStore.insertUint256Multi([key, key2], [10, 20], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple bytes32 into multiple Array", async () => { + await catchRevert(I_DataStore.insertBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple address into multiple Array", async () => { + await catchRevert(I_DataStore.insertAddressMulti([key, key2], [address_one, address_two], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple bool into multiple Array", async () => { + await catchRevert(I_DataStore.insertBoolMulti([key, key2], [true, true], { from: account_polymath })); + }); }); }); \ No newline at end of file From 4a487600c1eb308b86628bc88e75319aad7548f9 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 24 Jan 2019 15:06:50 +0530 Subject: [PATCH 075/119] Signed TM added --- .../KYCTransferManagerFactory.sol | 3 +- .../TransferManager/SignedTransferManager.sol | 184 ++++++++++++++++++ .../SignedTransferManagerFactory.sol | 110 +++++++++++ 3 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 contracts/modules/Experimental/TransferManager/SignedTransferManager.sol create mode 100644 contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol index 13c9bc5a2..8a5d8f23c 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol @@ -38,8 +38,9 @@ contract KYCTransferManagerFactory is ModuleFactory { * @notice Type of the Module factory */ function getTypes() external view returns(uint8[] memory) { - uint8[] memory res = new uint8[](1); + uint8[] memory res = new uint8[](2); res[0] = 2; + res[1] = 6; return res; } diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol new file mode 100644 index 000000000..236182e1e --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -0,0 +1,184 @@ +pragma solidity ^0.5.0; + +import "../../TransferManager/TransferManager.sol"; +import "../../../interfaces/IDataStore.sol"; +import "../../../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module for verifing transations with a signed message + */ +contract SignedTransferManager is TransferManager { + using SafeMath for uint256; + + bytes32 constant public ADMIN = "ADMIN"; + + //Keeps track of if the signature has been used or invalidated + //mapping(bytes => bool) invalidSignatures; + bytes32 constant public INVALID_SIG = "INVALIDSIG"; + + //keep tracks of the address that allows to sign messages + //mapping(address => bool) public signers; + bytes32 constant public SIGNER = "SIGNER"; + + // Emit when signer stats was changed + event SignersUpdated(address[] _signers, bool[] _signersStats); + + // Emit when a signature has been deemed invalid + event SignatureInvalidated(bytes _data); + + + /** + * @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() external pure returns (bytes4) { + return bytes4(0); + } + + /** + * @notice function to check if a signature is still valid + * @param _data signature + */ + function checkSignatureIsInvalid(bytes calldata _data) external view returns(bool) { + return _checkSignatureIsInvalid(_data); + } + + function checkSigner(address _signer) external view returns(bool) { + return _checkSigner(_signer); + } + + /** + * @notice function to remove or add signer(s) onto the signer mapping + * @param _signers address array of signers + * @param _signersStats bool array of signers stats + */ + function updateSigners(address[] memory _signers, bool[] memory _signersStats) external withPerm(ADMIN) { + require(_signers.length == _signersStats.length, "Array length mismatch"); + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + for(uint256 i=0; i<_signers.length; i++) { + require(_signers[i] != address(0), "Invalid address"); + dataStore.setBool(keccak256(abi.encodePacked(SIGNER, _signers[i])), _signersStats[i]); + } + emit SignersUpdated(_signers, _signersStats); + } + + /** + * @notice allow verify transfer with signature + * @param _from address transfer from + * @param _to address transfer to + * @param _amount transfer amount + * @param _data signature + * @param _isTransfer bool value of isTransfer + * Sig needs to be valid (not used or deemed as invalid) + * Signer needs to be in the signers mapping + */ + function verifyTransfer(address _from, address _to, uint256 _amount, bytes memory _data , bool _isTransfer) public returns(Result) { + if (!paused) { + + require (_isTransfer == false || msg.sender == securityToken, "Sender is not ST"); + + if (_data.length == 0 || _checkSignatureIsInvalid(_data)) { + return Result.NA; + } + + bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + address signer = _recoverSignerAdd(prependedHash, _data); + + if (!_checkSigner(signer)) { + return Result.NA; + } else if(_isTransfer) { + _invalidateSignature(_data); + return Result.VALID; + } else { + return Result.VALID; + } + } + return Result.NA; + } + + /** + * @notice allow signers to deem a signature invalid + * @param _from address transfer from + * @param _to address transfer to + * @param _amount transfer amount + * @param _data signature + * Sig needs to be valid (not used or deemed as invalid) + * Signer needs to be in the signers mapping + */ + function invalidateSignature(address _from, address _to, uint256 _amount, bytes calldata _data) external { + require(_checkSigner(signer), "Unauthorized Signer"); + require(!_checkSignatureIsInvalid(_data), "Signature already invalid"); + + bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + + require(_recoverSignerAdd(prependedHash, _data) == msg.sender, "Incorrect Signer"); + + _invalidateSignature(_data); + } + + /** + * @notice used to recover signers' address from signature + */ + function _recoverSignerAdd(bytes32 _hash, bytes memory _data) internal pure returns(address) { + + if (_data.length != 65) { + return address(0); + } + + bytes32 r; + bytes32 s; + uint8 v; + + assembly { + r := mload(add(_data, 32)) + s := mload(add(_data, 64)) + v := and(mload(add(_data, 65)), 255) + } + if (v < 27) { + v += 27; + } + if (v != 27 && v != 28) { + + } + + return ecrecover(_hash, v, r, s); + } + + /** + * @notice Return the permissions flag that are associated with ManualApproval transfer manager + */ + function getPermissions() public view returns(bytes32[] memory) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } + + function _checkSignatureIsInvalid(bytes memory _data) internal view returns(bool) { + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + return dataStore.getBool(keccak256(abi.encodePacked(INVALID_SIG, _data))); + } + + function _checkSigner(address _signer) internal view returns(bool) { + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + return dataStore.getBool(keccak256(abi.encodePacked(SIGNER, _signer))); + } + + function _invalidateSignature(bytes memory _data) internal { + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + dataStore.setBool(keccak256(abi.encodePacked(INVALID_SIG, _data)), true); + emit SignatureInvalidated(_data); + } +} diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol new file mode 100644 index 000000000..1617a4884 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol @@ -0,0 +1,110 @@ +pragma solidity ^0.5.0; + +import "./SignedTransferManager.sol"; +import "../../ModuleFactory.sol"; + +/** + * @title Factory for deploying SignedTransferManager module + */ +contract SignedTransferManagerFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "SignedTransferManager"; + title = "Signed Transfer Manager"; + description = "Manage transfers using a signature"; + 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 calldata /* _data */) external returns(address) { + // if (setupCost > 0) + // require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + // address signedTransferManager = new SignedTransferManager(msg.sender, address(polyToken)); + // emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, setupCost, now); + // return address(signedTransferManager); + // } + + function deploy(bytes calldata /* _data */) external returns(address) { + address polyToken = _takeFee(); + SignedTransferManager signedTransferManager = new SignedTransferManager(msg.sender, polyToken); + emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, now); + return address(signedTransferManager); + } + + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[] memory) { + uint8[] memory res = new uint8[](2); + res[0] = 2; + res[1] = 6; + 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 memory) { + return description; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string memory) { + return version; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string memory) { + return title; + } + + /** + * @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 memory) { + return "Allows an issuer to maintain a list of signers who can validate transfer request using signatures. A mapping is used to track valid signers which can be managed by the issuer. verifytransfer function takes in a signature and if the signature is valid, it will verify the transfer. invalidSigature function allow the signer to make a signature invalid after it is signed. Init function takes no parameters."; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[] memory) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "General"; + availableTags[1] = "Transfer Restriction"; + return availableTags; + } + + +} From 938c8e71d5c43686535163d428e8c3d015bed99f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 24 Jan 2019 15:07:04 +0530 Subject: [PATCH 076/119] web3 updated --- package.json | 2 +- yarn.lock | 332 +++++++++++++++++++++++++-------------------------- 2 files changed, 166 insertions(+), 168 deletions(-) diff --git a/package.json b/package.json index 809f9148e..a30b1040a 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "request-promise": "^4.2.2", "truffle-contract": "^3.0.4", "truffle-hdwallet-provider-privkey": "0.2.0", - "web3": "1.0.0-beta.34" + "web3": "1.0.0-beta.35" }, "devDependencies": { "@soldoc/soldoc": "^0.4.3", diff --git a/yarn.lock b/yarn.lock index fbe3ccc99..05f706a51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -139,7 +139,7 @@ ajv@^6.5.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.5.5, ajv@^6.6.1: +ajv@^6.5.5: version "6.6.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g== @@ -196,7 +196,7 @@ ansi-styles@^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: +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== @@ -318,11 +318,6 @@ assign-symbols@^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" @@ -2654,10 +2649,10 @@ eslint@^5.8.0: table "^5.0.2" text-table "^0.2.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== +espree@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" + integrity sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w== dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -4238,6 +4233,11 @@ 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" + 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" @@ -4670,7 +4670,7 @@ lodash.debounce@^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.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: +lodash@4.x, lodash@=4.17.11, lodash@^4.13.1, lodash@^4.14.2, lodash@^4.17.10, 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== @@ -6104,7 +6104,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^2.0.1: +regexpp@^2.0.0, regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -6621,13 +6621,11 @@ slash@^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== +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: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: @@ -7729,87 +7727,87 @@ watchr@~2.4.13: taskgroup "^4.2.0" typechecker "^2.0.8" -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= +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.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= +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.34" - web3-utils "1.0.0-beta.34" + web3-eth-iban "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -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= +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.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-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.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= +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.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= +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.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-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.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= +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.34" + web3-core-helpers "1.0.0-beta.35" -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= +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.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-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.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= +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: 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-core-helpers "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" -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= +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" @@ -7817,70 +7815,70 @@ web3-eth-accounts@1.0.0-beta.34: scrypt.js "0.2.0" underscore "1.8.3" uuid "2.0.1" - 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-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.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= +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.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= + 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.34" + web3-utils "1.0.0-beta.35" -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= +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.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-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.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= +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.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-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-provider-engine@^13.8.0: version "13.8.0" @@ -7927,46 +7925,46 @@ web3-provider-engine@^8.4.0: xhr "^2.2.0" xtend "^4.0.1" -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= +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.34" - xhr2 "0.1.4" + web3-core-helpers "1.0.0-beta.35" + xhr2-cookies "1.1.0" -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= +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.34" + web3-core-helpers "1.0.0-beta.35" -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= +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.34" + web3-core-helpers "1.0.0-beta.35" 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= +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.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-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.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= +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" @@ -8009,18 +8007,18 @@ web3@0.20.6: xhr2 "*" xmlhttprequest "*" -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= +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.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" + 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" web3@^0.16.0: version "0.16.0" @@ -8227,14 +8225,14 @@ xhr-request@^1.0.1: url-set-query "^1.0.0" xhr "^2.0.4" -xhr2-cookies@^1.1.0: +xhr2-cookies@1.1.0, 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: +xhr2@*: version "0.1.4" resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= From 75a086f7efd0f14ab106c2fe20bbab6b1ba8ef67 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 24 Jan 2019 15:07:14 +0530 Subject: [PATCH 077/119] wip --- test/zb_signed_transfer_manager.js | 305 +++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 test/zb_signed_transfer_manager.js diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js new file mode 100644 index 000000000..3202ad595 --- /dev/null +++ b/test/zb_signed_transfer_manager.js @@ -0,0 +1,305 @@ +import latestTime from "./helpers/latestTime"; +import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; +import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; +import { signDataVerifyTransfer } from "./helpers/signData"; +import { pk } from "./helpers/testprivateKey"; +import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed, deploySignedTMAndVerifyed} from "./helpers/createInstances"; + +const DummySTO = artifacts.require("./DummySTO.sol"); +const SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const SignedTransferManager = artifacts.require("./SignedTransferManager"); + +const Web3 = require("web3"); +const BigNumber = require("bignumber.js"); +let BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +contract("SignedTransferManager", 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; + + // 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; + let I_SignedTransferManagerFactory; + let P_SignedTransferManagerFactory; + let I_SignedTransferManager; + + // 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"]; + + let currentTime; + + before(async () => { + // Accounts setup + currentTime = new BN(await latestTime()); + 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[6]; + account_investor4 = accounts[7]; + + // 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 GeneralPermissionManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 3: Deploy the SignedTransferManagerFactory + [I_SignedTransferManagerFactory] = await deploySignedTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 4: Deploy the Paid SignedTransferManagerFactory + [P_SignedTransferManagerFactory] = await deploySignedTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); + + // 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} + + ManualApprovalTransferManagerFactory: ${I_SignedTransferManagerFactory.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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // 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 = await GeneralTransferManager.at(moduleData); + }); + }); + + + describe("signed transfer manager tests", async () => { + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + currentTime, + currentTime, + currentTime.add(new BN(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, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + }); + + + it("Should successfully attach the SignedTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_SignedTransferManagerFactory.address, new BN(0),new BN(0),new BN(0), { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "SignedTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toUtf8(tx.logs[2].args._name), + "SignedTransferManager", + "SignedTransferManager module was not added" + ); + console.log(tx.logs[2].args); + I_SignedTransferManager = await SignedTransferManager.at(tx.logs[2].args._module); + }); + + it("should fail to transfer because transaction is not verified yet.", async () => { + await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + }); + + it("should successfully add multiple signers to signersList", async () => { + await I_SignedTransferManager.updateSigners([account_investor3, account_investor4, token_owner], [true, true, true], {from: token_owner}); + + assert.equal(await I_SignedTransferManager.signers(account_investor3), true); + assert.equal(await I_SignedTransferManager.signers(account_investor4), true); + assert.equal(await I_SignedTransferManager.signers(token_owner), true); + }); + + it("should fail to change signers stats without permission", async () => { + await catchRevert(I_SignedTransferManager.updateSigners([account_investor3], [false], {from: account_investor2})); + }); + + + it("should be able to invalid siganture if sender is the signer and is in the signer list", async () => { + + console.log("1"); + + const sig = await signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("2", "ether"), + token_owner + ); + + console.log("token owner is "+ token_owner); + console.log(sig); + + await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("2", "ether"), sig, {from: token_owner}); + console.log("sd"); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); + }); + + it("should allow transfer with valid sig", async () => { + + console.log("owner is a signer status is " + await I_SignedTransferManager.signers(token_owner, {from: token_owner})); + + const sig = await signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + token_owner + ); + + // let tx = await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); + console.log("owner token balance is " + (await I_SecurityToken.balanceOf(account_investor1)).toNumber()); + console.log("is this sig invalid?"+ await I_SignedTransferManager.checkSignatureIsInvalid(sig)); + + // test call security token transfer function + let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1}); + console.log("3"); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); + }); + + it("should not allow transfer if the sig is already used", async () => { + const sig = await signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + token_owner + ); + + console.log("2"); + + await catchRevert (I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner})); + }); + + it("should not allow transfer if the signer is not on the signer list", async () => { + const sig = await signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor2 + ); + + let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); + console.log("output is "+tx.toNumber()); + + }); + + }); +}); + From 2c2c4996e9897763300a548b67f3e57b95b5345f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 24 Jan 2019 15:22:05 +0530 Subject: [PATCH 078/119] Fixed compilation --- .../Experimental/TransferManager/SignedTransferManager.sol | 4 ++-- .../TransferManager/SignedTransferManagerFactory.sol | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index 236182e1e..b72241eca 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -63,7 +63,7 @@ contract SignedTransferManager is TransferManager { * @param _signers address array of signers * @param _signersStats bool array of signers stats */ - function updateSigners(address[] memory _signers, bool[] memory _signersStats) external withPerm(ADMIN) { + function updateSigners(address[] calldata _signers, bool[] calldata _signersStats) external withPerm(ADMIN) { require(_signers.length == _signersStats.length, "Array length mismatch"); IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); for(uint256 i=0; i<_signers.length; i++) { @@ -118,7 +118,7 @@ contract SignedTransferManager is TransferManager { * Signer needs to be in the signers mapping */ function invalidateSignature(address _from, address _to, uint256 _amount, bytes calldata _data) external { - require(_checkSigner(signer), "Unauthorized Signer"); + require(_checkSigner(msg.sender), "Unauthorized Signer"); require(!_checkSignatureIsInvalid(_data), "Signature already invalid"); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol index 1617a4884..d38d82758 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol @@ -10,9 +10,8 @@ contract SignedTransferManagerFactory is ModuleFactory { /** * @notice Constructor - * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; From 6c99e9eef1c1820d35216b6bbafc790bd86279ef Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 24 Jan 2019 17:01:49 +0530 Subject: [PATCH 079/119] Added tests --- test/helpers/createInstances.js | 14 ++++ test/helpers/signData.js | 9 ++- test/zb_signed_transfer_manager.js | 102 +++++++++++------------------ 3 files changed, 61 insertions(+), 64 deletions(-) diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index d8d9b93da..332767d8d 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -41,6 +41,7 @@ const STRGetter = artifacts.require("./STRGetter.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); const DataStoreLogic = artifacts.require('./DataStore.sol'); const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); +const SignedTransferManagerFactory = artifacts.require("./SignedTransferManagerFactory"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -88,6 +89,7 @@ let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; let I_STRGetter; +let I_SignedTransferManagerFactory; // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); @@ -494,3 +496,15 @@ export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, await registerAndVerifyByMR(I_MockWrongTypeBurnFactory.address, accountPolymath, MRProxyInstance); return Promise.all(new Array(I_MockWrongTypeBurnFactory)); } + +export async function deploySignedTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_SignedTransferManagerFactory = await SignedTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + assert.notEqual( + I_SignedTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SignedTransferManagerFactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_SignedTransferManagerFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_SignedTransferManagerFactory); +} \ No newline at end of file diff --git a/test/helpers/signData.js b/test/helpers/signData.js index f75572450..581ebcea9 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -18,6 +18,13 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } +function getSignTMSig(tmAddress, fromAddress, toAddress, amount, pk) { + let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: fromAddress}, {t: 'address', v: toAddress}, {t: 'uint256', v: new BN(amount)}); + let sign = web3.eth.accounts.sign(hash, pk); + return sign.signature; +} + module.exports = { - signData + signData, + getSignTMSig }; diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index 3202ad595..10859d1ab 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -1,11 +1,11 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; -import { signDataVerifyTransfer } from "./helpers/signData"; +import { getSignTMSig } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed, deploySignedTMAndVerifyed} from "./helpers/createInstances"; +import { setUpPolymathNetwork, deployGPMAndVerifyed, deploySignedTMAndVerifyed} from "./helpers/createInstances"; const DummySTO = artifacts.require("./DummySTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); @@ -29,13 +29,6 @@ contract("SignedTransferManager", accounts => { 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_GeneralTransferManagerFactory; @@ -73,13 +66,6 @@ contract("SignedTransferManager", accounts => { // 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"]; - let currentTime; before(async () => { @@ -209,7 +195,6 @@ contract("SignedTransferManager", accounts => { "SignedTransferManager", "SignedTransferManager module was not added" ); - console.log(tx.logs[2].args); I_SignedTransferManager = await SignedTransferManager.at(tx.logs[2].args._module); }); @@ -220,9 +205,9 @@ contract("SignedTransferManager", accounts => { it("should successfully add multiple signers to signersList", async () => { await I_SignedTransferManager.updateSigners([account_investor3, account_investor4, token_owner], [true, true, true], {from: token_owner}); - assert.equal(await I_SignedTransferManager.signers(account_investor3), true); - assert.equal(await I_SignedTransferManager.signers(account_investor4), true); - assert.equal(await I_SignedTransferManager.signers(token_owner), true); + assert.equal(await I_SignedTransferManager.checkSigner(account_investor3), true); + assert.equal(await I_SignedTransferManager.checkSigner(account_investor4), true); + assert.equal(await I_SignedTransferManager.checkSigner(token_owner), true); }); it("should fail to change signers stats without permission", async () => { @@ -230,76 +215,67 @@ contract("SignedTransferManager", accounts => { }); - it("should be able to invalid siganture if sender is the signer and is in the signer list", async () => { - - console.log("1"); + it("should allow to invalidate siganture if sender is the signer and is in the signer list", async () => { + let oneeth = new BN(web3.utils.toWei("1", "ether")); + let signer = web3.eth.accounts.create(); + await web3.eth.personal.importRawKey(signer.privateKey, ""); + await web3.eth.personal.unlockAccount(signer.address, "", 6000); + await web3.eth.sendTransaction({ from: token_owner, to: signer.address, value: oneeth }); - const sig = await signDataVerifyTransfer( + await I_SignedTransferManager.updateSigners([signer.address], [true], {from: token_owner}); + + const sig = await getSignTMSig( I_SignedTransferManager.address, account_investor1, account_investor2, - web3.utils.toWei("2", "ether"), - token_owner + oneeth, + signer.privateKey ); - console.log("token owner is "+ token_owner); - console.log(sig); - - await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("2", "ether"), sig, {from: token_owner}); - console.log("sd"); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), false); + await I_SignedTransferManager.invalidateSignature(account_investor1, account_investor2, oneeth, sig, {from: signer.address}); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); it("should allow transfer with valid sig", async () => { + let signer = web3.eth.accounts.create(); + await I_SignedTransferManager.updateSigners([signer.address], [true], {from: token_owner}); + let oneeth = new BN(web3.utils.toWei("1", "ether")); - console.log("owner is a signer status is " + await I_SignedTransferManager.signers(token_owner, {from: token_owner})); - - const sig = await signDataVerifyTransfer( + const sig = await getSignTMSig( I_SignedTransferManager.address, account_investor1, account_investor2, - web3.utils.toWei("1", "ether"), - token_owner + oneeth, + signer.privateKey ); - // let tx = await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); - console.log("owner token balance is " + (await I_SecurityToken.balanceOf(account_investor1)).toNumber()); - console.log("is this sig invalid?"+ await I_SignedTransferManager.checkSignatureIsInvalid(sig)); - - // test call security token transfer function - let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1}); - console.log("3"); + let balance11 = await I_SecurityToken.balanceOf(account_investor1); + let balance21 = await I_SecurityToken.balanceOf(account_investor2); + + await I_SecurityToken.transferWithData(account_investor2, oneeth, sig, {from: account_investor1}); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); - }); + assert.equal(balance11.sub(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor1)).toString()); + assert.equal(balance21.add(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor2)).toString()); - it("should not allow transfer if the sig is already used", async () => { - const sig = await signDataVerifyTransfer( - I_SignedTransferManager.address, - account_investor1, - account_investor2, - web3.utils.toWei("1", "ether"), - token_owner - ); - - console.log("2"); - - await catchRevert (I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner})); + await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, sig, {from: account_investor1})); }); it("should not allow transfer if the signer is not on the signer list", async () => { - const sig = await signDataVerifyTransfer( + let signer = web3.eth.accounts.create(); + let oneeth = new BN(web3.utils.toWei("1", "ether")); + + const sig = await getSignTMSig( I_SignedTransferManager.address, account_investor1, account_investor2, - web3.utils.toWei("1", "ether"), - account_investor2 + oneeth, + signer.privateKey ); - let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); - console.log("output is "+tx.toNumber()); - + await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, sig, {from: account_investor1})); }); - }); }); From ea444a0755d74dd97dba197ff052c4eb304a533b Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 25 Jan 2019 13:42:38 +0530 Subject: [PATCH 080/119] Added more params to hash input --- .../TransferManager/SignedTransferManager.sol | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index b72241eca..908fb26be 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -50,8 +50,15 @@ contract SignedTransferManager is TransferManager { * @notice function to check if a signature is still valid * @param _data signature */ - function checkSignatureIsInvalid(bytes calldata _data) external view returns(bool) { - return _checkSignatureIsInvalid(_data); + function checkSignatureValidity(bytes calldata _data) external view returns(bool) { + address targetAddress; + uint256 nonce; + uint256 expiry; + bytes memory signature; + (targetAddress, nonce, expiry, signature) = abi.decode(_data, (address, uint256, uint256, bytes)); + if (targetAddress != address(this) || expiry < now || signature.length == 0 || _checkSignatureIsInvalid(signature)) + return false; + return true; } function checkSigner(address _signer) external view returns(bool) { @@ -88,18 +95,26 @@ contract SignedTransferManager is TransferManager { require (_isTransfer == false || msg.sender == securityToken, "Sender is not ST"); - if (_data.length == 0 || _checkSignatureIsInvalid(_data)) { + if (_data.length == 0) return Result.NA; - } - bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + address targetAddress; + uint256 nonce; + uint256 expiry; + bytes memory signature; + (targetAddress, nonce, expiry, signature) = abi.decode(_data, (address, uint256, uint256, bytes)); + + if (address(this) != targetAddress || signature.length == 0 || _checkSignatureIsInvalid(signature) || expiry < now) + return Result.NA; + + bytes32 hash = keccak256(abi.encodePacked(targetAddress, nonce, expiry, _from, _to, _amount)); bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - address signer = _recoverSignerAdd(prependedHash, _data); + address signer = _recoverSignerAdd(prependedHash, signature); if (!_checkSigner(signer)) { return Result.NA; } else if(_isTransfer) { - _invalidateSignature(_data); + _invalidateSignature(signature); return Result.VALID; } else { return Result.VALID; @@ -119,14 +134,22 @@ contract SignedTransferManager is TransferManager { */ function invalidateSignature(address _from, address _to, uint256 _amount, bytes calldata _data) external { require(_checkSigner(msg.sender), "Unauthorized Signer"); - require(!_checkSignatureIsInvalid(_data), "Signature already invalid"); + + address targetAddress; + uint256 nonce; + uint256 expiry; + bytes memory signature; + (targetAddress, nonce, expiry, signature) = abi.decode(_data, (address, uint256, uint256, bytes)); + + require(!_checkSignatureIsInvalid(signature), "Signature already invalid"); + require(targetAddress != address(this), "Signature not for this module"); - bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + bytes32 hash = keccak256(abi.encodePacked(targetAddress, nonce, expiry, _from, _to, _amount)); bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - require(_recoverSignerAdd(prependedHash, _data) == msg.sender, "Incorrect Signer"); + require(_recoverSignerAdd(prependedHash, signature) == msg.sender, "Incorrect Signer"); - _invalidateSignature(_data); + _invalidateSignature(signature); } /** From f3dc1b38acb1946604932d742ad187a20c4321e2 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 25 Jan 2019 13:42:53 +0530 Subject: [PATCH 081/119] code comments for data store --- contracts/datastore/DataStore.sol | 1 + contracts/tokens/STFactory.sol | 1 + 2 files changed, 2 insertions(+) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 29d2e2b1d..c722d49d1 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -43,6 +43,7 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _securityToken address of the security token */ function setSecurityToken(address _securityToken) external onlyOwner { + //NB When dataStore is generated, the security token address is automatically set via the constructor in DataStoreProxy. if(address(securityToken) != address(0)) { require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); } diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index d00e7e192..8c78c04ff 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -41,6 +41,7 @@ contract STFactory is ISTFactory { _polymathRegistry ); newSecurityToken.addModule(transferManagerFactory, "", 0, 0); + //NB When dataStore is generated, the security token address is automatically set via the constructor in DataStoreProxy. newSecurityToken.changeDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); newSecurityToken.transferOwnership(_issuer); return address(newSecurityToken); From 772d2f29ef619e738aed39ece54fce9c1eba66cd Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 25 Jan 2019 14:10:15 +0530 Subject: [PATCH 082/119] Updated tests --- .../TransferManager/SignedTransferManager.sol | 2 +- test/helpers/signData.js | 11 ++--- test/zb_signed_transfer_manager.js | 40 +++++++++++++------ 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index 908fb26be..ea7edffe9 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -142,7 +142,7 @@ contract SignedTransferManager is TransferManager { (targetAddress, nonce, expiry, signature) = abi.decode(_data, (address, uint256, uint256, bytes)); require(!_checkSignatureIsInvalid(signature), "Signature already invalid"); - require(targetAddress != address(this), "Signature not for this module"); + require(targetAddress == address(this), "Signature not for this module"); bytes32 hash = keccak256(abi.encodePacked(targetAddress, nonce, expiry, _from, _to, _amount)); bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 581ebcea9..cb551102e 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -18,13 +18,14 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } -function getSignTMSig(tmAddress, fromAddress, toAddress, amount, pk) { - let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: fromAddress}, {t: 'address', v: toAddress}, {t: 'uint256', v: new BN(amount)}); - let sign = web3.eth.accounts.sign(hash, pk); - return sign.signature; +function getSignTMData(tmAddress, nonce, expiry, fromAddress, toAddress, amount, pk) { + let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'uint256', v: new BN(nonce)}, {t: 'uint256', v: new BN(expiry)}, {t: 'address', v: fromAddress}, {t: 'address', v: toAddress}, {t: 'uint256', v: new BN(amount)}); + let signature = (web3.eth.accounts.sign(hash, pk)).signature; + let data = web3.eth.abi.encodeParameters(['address', 'uint256', 'uint256', 'bytes'], [tmAddress, new BN(nonce).toString(), new BN(expiry).toString(), signature]); + return data; } module.exports = { signData, - getSignTMSig + getSignTMData }; diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index 10859d1ab..e13b99f46 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -1,7 +1,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; -import { getSignTMSig } from "./helpers/signData"; +import { getSignTMData } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; @@ -224,26 +224,33 @@ contract("SignedTransferManager", accounts => { await I_SignedTransferManager.updateSigners([signer.address], [true], {from: token_owner}); - const sig = await getSignTMSig( + let nonce = new BN(10); + let expiry = new BN(currentTime.add(new BN(duration.days(100)))); + let data = await getSignTMData( I_SignedTransferManager.address, + nonce, + expiry, account_investor1, account_investor2, oneeth, signer.privateKey ); - assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), false); - await I_SignedTransferManager.invalidateSignature(account_investor1, account_investor2, oneeth, sig, {from: signer.address}); - assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); + assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), true); + await I_SignedTransferManager.invalidateSignature(account_investor1, account_investor2, oneeth, data, {from: signer.address}); + assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), false); }); it("should allow transfer with valid sig", async () => { let signer = web3.eth.accounts.create(); await I_SignedTransferManager.updateSigners([signer.address], [true], {from: token_owner}); let oneeth = new BN(web3.utils.toWei("1", "ether")); - - const sig = await getSignTMSig( + let nonce = new BN(10); + let expiry = new BN(currentTime.add(new BN(duration.days(100)))); + let data = await getSignTMData( I_SignedTransferManager.address, + nonce, + expiry, account_investor1, account_investor2, oneeth, @@ -253,28 +260,35 @@ contract("SignedTransferManager", accounts => { let balance11 = await I_SecurityToken.balanceOf(account_investor1); let balance21 = await I_SecurityToken.balanceOf(account_investor2); - await I_SecurityToken.transferWithData(account_investor2, oneeth, sig, {from: account_investor1}); + assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), true); + + await I_SecurityToken.transferWithData(account_investor2, oneeth, data, {from: account_investor1}); + + assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), false); + await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, data, {from: account_investor1})); - assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); assert.equal(balance11.sub(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor1)).toString()); assert.equal(balance21.add(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor2)).toString()); - await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, sig, {from: account_investor1})); + }); it("should not allow transfer if the signer is not on the signer list", async () => { let signer = web3.eth.accounts.create(); let oneeth = new BN(web3.utils.toWei("1", "ether")); - - const sig = await getSignTMSig( + let nonce = new BN(10); + let expiry = new BN(currentTime.add(new BN(duration.days(100)))); + let data = await getSignTMData( I_SignedTransferManager.address, + nonce, + expiry, account_investor1, account_investor2, oneeth, signer.privateKey ); - await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, sig, {from: account_investor1})); + await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, data, {from: account_investor1})); }); }); }); From f269c99a3484030917afb0fb473bb83b3f09056b Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 28 Jan 2019 14:02:41 +0530 Subject: [PATCH 083/119] minor fixes --- contracts/datastore/DataStore.sol | 18 +++++++++--------- .../TransferManager/KYCTransferManager.sol | 7 ++----- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 29d2e2b1d..3bef0b6a0 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -28,7 +28,7 @@ contract DataStore is DataStoreStorage, IDataStore { _; } - modifier validInputLength(uint256 _keyLength, uint256 _dataLength) { + modifier validArrayLength(uint256 _keyLength, uint256 _dataLength) { require(_keyLength == _dataLength, "Array length mismatch"); _; } @@ -147,25 +147,25 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _keys Array of keys to identify the data * @param _data Array of data to be stored against the respective keys */ - function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } } - function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _setData(_keys[i], _data[i]); } @@ -176,25 +176,25 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _keys Array of keys to identify the data * @param _data Array of data to be inserted in arrays of the respective keys */ - function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } } - function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validInputLength(_keys.length, _data.length) { + function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { for (uint256 i = 0; i < _keys.length; i++) { _insertData(_keys[i], _data[i]); } diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol index f43a9cd64..7a314220e 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -40,11 +40,8 @@ contract KYCTransferManager is TransferManager { public returns (Result) { - if (!paused) { - bytes32 key = _getKYCKey(_to); - IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); - if (dataStore.getUint256(key) > 0) - return Result.VALID; + if (!paused && checkKYC(_to)) { + return Result.VALID; } return Result.NA; } From 40d5b3874592a5b2b7ee0b4d8c45d228bdd4ee13 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 28 Jan 2019 07:56:50 -0400 Subject: [PATCH 084/119] dev 2.1 > dev 3.0 (#521) * Updated changelog * Changed currencyRaised to stableCoinsRaised * MATM contract and test fixes * minor fix * CLI - LockupTM support * individual balance for every stable coin listed * CLI minor fixes * recommended fixes * Added code comments * Removed uninitialized pointer * CLI - Fixes for new contract changes * Minor fix * trying by adding some buffer in time travel * [WIP] CLI advances * modify function changes * WIP * CircleCI changes * CircleCI changes * CircleCI changes * Badge * Store test results * Removed coverage from commit workflow * CLI - WIP VolumeRestrictionTM support * CLI - Removed STVR TM from CLI * Added test reporter * Addded artifact collection * Added parallelism * Comment * Bumped parallelism to 3 * Coverage requires approval * Bumped parallelism to 4 * Removed manual approval * Combine travis and CircleCI * env var changes * comment * Improve MATM to allow allowances and expiryTimes to be changed for existing approvals * Refactoring and improvements * CLI - Operations in batch for VRTM * fuzz test for adding and removing modules * finished module fuzz test * Fix rounding off errors (#467) * Fixed rounding off errors * Increased tolerance * Reduced tolerance to zero * Comment updated * Tolerance set to 2 * Minor CLI changes * fix modify batch * Increased no o/p timeout * Improve menu string * Triggering CircleCI * CLI minor changes * Add ability to see excluded addresses * Updates * Fixes * Bump excluded limit to 150 * remove SRVTM * Use investor list from checkpoint * CLI - Script to generate tokens, whitelist investors and mint to them * CLI - Explore account * Update PolyTokenFaucet.sol * Improved the natspec comments * added VestingEscrowWalletLogic to output * Track withheld at dividend granularity * wip - issue with test not finishing * removed redundant dependencies * increased versions * WIP-multiple transaction within 1 day with Individual and daily Restrictions * updated yarn.lock * Add balances & claim amounts to getters * CLI - Flow change and updates for dividends_manager * Updated test script * Script updated * fixed bug with the initial test * Update test.sh * Script updated * coverage block gas limit increased * ganache-cli 6.2.5 * Travis submit coverage * added scenario 2 and 3 * fix input random number issue * Add more test cases * CLI Minor fixes * 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. * Add getCheckpointData * CLI minor changes * CLI typo fix * bug fixes * CLI updates * finished test case 4 * repeat period count from the startTime * WIP * fixed functions getActiveApprovalsToUser and added getAllApprovals() both will return all approval details in multiple arrays as requested * edited function description * Bumped cappedSTO version * MATM version bumped * CLI update * test case fixed * Update j_manual_approval_transfer_manager.js * WIP * reinvent the test case * Merge conflicts * indexing the param (#500) * Permissions update * Removed redundant events * dual truffle coverage * VRTM coverage fix * Added compile command * Updated coverage script * removed compile command * Updated truffle config * 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 * add getRestrictedAddresses() function * minor fix * Fixed test file * Add restrictions data to getRestrictedAddresses * Remove commented code and better tests * modified the getRestrictedAddress() function * code cleanup * CLI - Show restrictions table * minor fix * CLI - Update method name, updated csv dates * Trigger TravisCI * CLI - Changed names of restrictions * Minor fix * CLI - Percentage with decimals fix * CLI - Changed names of restrictions * add exempt list getter * minor fix * CLI - Added 'show exempted addresses' * Small optimisation * compilation errors * compilation errors in modules * compilation errors * 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 * removed polyToken from factories * Fix comments (#519) * Fix STR size * fixed b_capped_sto.js * capped_sto fix * Remove duped test cases * Fix erc20 test * More fixes * fixes for h_general_transfer_manager.js * fixes for h_general_transfer_manager.js * fixes for j_manual_approval_transfer_manager.js * fixed n_security_token_registry.js * h_general_transfer_manager.js -removed redundant block due to merge issue * fixes for u_module_registry_proxy.js * fixes for z_vesting_escrow_wallet.js * fixes for z_vesting_escrow_wallet.js * 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 * Fix MATM test case * fixes for z_vesting_escrow_wallet.js * Update * Remove unnecessary import * Clean up some imports * Small size optimisation and migrate fix * fixes for z_vesting_escrow_wallet.js * fixes for z_vesting_escrow_wallet.js (finished) * fixes for y_volume_restriction_tm.js * fixes for y_volume_restriction_tm.js * Some struct refactoring. * Some more optimisations * Some more optimisations * Merge 2.1 fix * More optimisations * Remove comments * Fixed imports in tests * Some updates * Some updates * WIP fixes * Some more updates * Add temp.js * Updates * Updates * Fixes * Fixes * Updates * usdtsto optimization (#534) * Initial optimization * Tests fixed * comments removed * Make some functions external * Updates * More fixes * Fix circle-ci * Add more tests --- .travis.yml | 2 +- 0 | 0 CLI/commands/ST20Generator.js | 4 +- CLI/commands/TickerRollForward.js | 18 +- CLI/commands/common/common_functions.js | 13 +- CLI/commands/common/constants.js | 2 +- CLI/commands/common/permissions_list.js | 74 +- CLI/commands/dividends_manager.js | 1221 +++++--- CLI/commands/helpers/contract_abis.js | 68 +- CLI/commands/helpers/contract_addresses.js | 18 +- CLI/commands/investor_portal.js | 201 +- CLI/commands/sto_manager.js | 285 +- CLI/commands/strMigrator.js | 14 +- CLI/commands/token_manager.js | 2 +- CLI/commands/transfer_manager.js | 2729 +++++++++++++---- CLI/data/Checkpoint/exclusions_data.csv | 5 + CLI/data/Checkpoint/tax_withholding_data.csv | 10 + .../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 + CLI/data/Transfer/GTM/whitelist_data.csv | 2 +- .../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 + .../Transfer/MATM/add_manualapproval_data.csv | 5 + .../MATM/modify_manualapproval_data.csv | 5 + .../MATM/revoke_manualapproval_data.csv | 2 + .../VRTM/add_custom_restriction_data.csv | 8 + .../VRTM/add_daily_restriction_data.csv | 8 + .../VRTM/modify_custom_restriction_data.csv | 5 + .../VRTM/modify_daily_restriction_data.csv | 5 + .../VRTM/remove_custom_restriction_data.csv | 2 + .../VRTM/remove_daily_restriction_data.csv | 6 + CLI/package.json | 2 +- CLI/polymath-cli.js | 14 +- CLI/scripts/stable_coin.sh | 18 + contracts/ModuleRegistry.sol | 36 +- contracts/STRGetter.sol | 40 +- contracts/SecurityTokenRegistry.sol | 98 +- contracts/interfaces/IBoot.sol | 2 +- contracts/interfaces/ICheckPermission.sol | 14 + .../libraries/BokkyPooBahsDateTimeLibrary.sol | 35 +- contracts/libraries/VolumeRestrictionLib.sol | 130 + contracts/mocks/PolyTokenFaucet.sol | 4 +- .../modules/Checkpoint/DividendCheckpoint.sol | 638 ++-- .../Checkpoint/DividendCheckpointStorage.sol | 22 +- .../Checkpoint/ERC20DividendCheckpoint.sol | 558 ++-- .../ERC20DividendCheckpointFactory.sol | 23 +- .../Checkpoint/EtherDividendCheckpoint.sol | 436 +-- .../EtherDividendCheckpointFactory.sol | 23 +- .../BlacklistTransferManager.sol | 399 +++ .../BlacklistTransferManagerFactory.sol | 68 + .../TransferManager/LockUpTransferManager.sol | 636 ++++ ...y.sol => LockUpTransferManagerFactory.sol} | 33 +- .../LockupVolumeRestrictionTM.sol | 403 --- .../SingleTradeVolumeRestrictionTM.sol | 338 -- .../SingleTradeVolumeRestrictionTMFactory.sol | 81 - .../modules/Experimental/Wallet/IWallet.sol | 19 + .../Wallet/VestingEscrowWallet.sol | 566 ++++ .../Wallet/VestingEscrowWalletFactory.sol | 75 + contracts/modules/Module.sol | 10 +- contracts/modules/ModuleFactory.sol | 12 - .../GeneralPermissionManager.sol | 7 +- contracts/modules/STO/CappedSTO.sol | 6 +- contracts/modules/STO/CappedSTOFactory.sol | 2 +- contracts/modules/STO/ISTOStorage.sol | 24 + contracts/modules/STO/STO.sol | 9 +- contracts/modules/STO/USDTieredSTO.sol | 435 ++- contracts/modules/STO/USDTieredSTOFactory.sol | 8 +- .../TransferManager/CountTransferManager.sol | 7 +- .../GeneralTransferManager.sol | 19 +- .../ManualApprovalTransferManager.sol | 341 +- .../ManualApprovalTransferManagerFactory.sol | 18 +- .../ManualApprovalTransferManagerStorage.sol | 16 +- .../PercentageTransferManager.sol | 10 +- .../TransferManager/VolumeRestrictionTM.sol | 1095 +++++++ .../VolumeRestrictionTMFactory.sol | 73 + .../proxy/ERC20DividendCheckpointProxy.sol | 10 +- .../proxy/EtherDividendCheckpointProxy.sol | 10 +- .../proxy/GeneralTransferManagerProxy.sol | 12 +- contracts/proxy/USDTieredSTOProxy.sol | 2 +- contracts/proxy/VestingEscrowWalletProxy.sol | 27 + contracts/proxy/VolumeRestrictionTMProxy.sol | 30 + contracts/storage/EternalStorage.sol | 64 +- .../GeneralTransferManagerStorage.sol | 2 +- .../STO => storage}/USDTieredSTOStorage.sol | 37 +- .../storage/VestingEscrowWalletStorage.sol | 54 + .../storage/VolumeRestrictionTMStorage.sol | 86 + contracts/tokens/SecurityToken.sol | 3 +- docs/permissions_list.md | 132 +- migrations/2_deploy_contracts.js | 32 +- module-labeling | 1 + scripts/test.sh | 2 +- scripts/tokenInfo-v1.js | 72 +- test/b_capped_sto.js | 13 +- test/d_count_transfer_manager.js | 4 +- test/e_erc20_dividends.js | 162 +- test/f_ether_dividends.js | 36 +- test/h_general_transfer_manager.js | 5 +- test/helpers/createInstances.js | 61 +- test/helpers/exceptions.js | 3 + test/j_manual_approval_transfer_manager.js | 552 +++- test/k_module_registry.js | 26 +- test/l_percentage_transfer_manager.js | 3 +- test/n_security_token_registry.js | 63 +- test/p_usd_tiered_sto.js | 192 +- test/q_usd_tiered_sto_sim.js | 88 +- test/t_security_token_registry_proxy.js | 8 +- test/u_module_registry_proxy.js | 10 +- test/w_lockup_transfer_manager.js | 966 ++++++ ...kup_volume_restriction_transfer_manager.js | 793 ----- ...ckpoints.js => x_scheduled_checkpoints.js} | 0 test/y_volume_restriction_tm.js | 1693 ++++++++++ test/z_blacklist_transfer_manager.js | 996 ++++++ .../z_fuzz_test_adding_removing_modules_ST.js | 310 ++ ...zer_volumn_restriction_transfer_manager.js | 723 +++++ test/z_general_permission_manager_fuzzer.js | 105 +- test/z_vesting_escrow_wallet.js | 1221 ++++++++ 122 files changed, 15479 insertions(+), 4717 deletions(-) create mode 100644 0 create mode 100644 CLI/data/Checkpoint/exclusions_data.csv create mode 100644 CLI/data/Checkpoint/tax_withholding_data.csv 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 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 create mode 100644 CLI/data/Transfer/MATM/add_manualapproval_data.csv create mode 100644 CLI/data/Transfer/MATM/modify_manualapproval_data.csv create mode 100644 CLI/data/Transfer/MATM/revoke_manualapproval_data.csv create mode 100644 CLI/data/Transfer/VRTM/add_custom_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/add_daily_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/modify_custom_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/remove_custom_restriction_data.csv create mode 100644 CLI/data/Transfer/VRTM/remove_daily_restriction_data.csv create mode 100755 CLI/scripts/stable_coin.sh create mode 100644 contracts/interfaces/ICheckPermission.sol create mode 100644 contracts/libraries/VolumeRestrictionLib.sol create mode 100644 contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol create mode 100644 contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol create mode 100644 contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol rename contracts/modules/Experimental/TransferManager/{LockupVolumeRestrictionTMFactory.sol => LockUpTransferManagerFactory.sol} (71%) delete mode 100644 contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol delete mode 100644 contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol delete mode 100644 contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol create mode 100644 contracts/modules/Experimental/Wallet/IWallet.sol create mode 100644 contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol create mode 100644 contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol create mode 100644 contracts/modules/STO/ISTOStorage.sol create mode 100644 contracts/modules/TransferManager/VolumeRestrictionTM.sol create mode 100644 contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol create mode 100644 contracts/proxy/VestingEscrowWalletProxy.sol create mode 100644 contracts/proxy/VolumeRestrictionTMProxy.sol rename contracts/{modules/TransferManager => storage}/GeneralTransferManagerStorage.sol (96%) rename contracts/{modules/STO => storage}/USDTieredSTOStorage.sol (67%) create mode 100644 contracts/storage/VestingEscrowWalletStorage.sol create mode 100644 contracts/storage/VolumeRestrictionTMStorage.sol create mode 100644 module-labeling create mode 100644 test/w_lockup_transfer_manager.js delete mode 100644 test/w_lockup_volume_restriction_transfer_manager.js rename test/{y_scheduled_checkpoints.js => x_scheduled_checkpoints.js} (100%) create mode 100644 test/y_volume_restriction_tm.js create mode 100644 test/z_blacklist_transfer_manager.js create mode 100644 test/z_fuzz_test_adding_removing_modules_ST.js create mode 100644 test/z_fuzzer_volumn_restriction_transfer_manager.js create mode 100644 test/z_vesting_escrow_wallet.js diff --git a/.travis.yml b/.travis.yml index f5f910f50..29ddc4a89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ cache: jobs: include: - stage: Test - install: + install: - echo -ne '\n' | sudo add-apt-repository ppa:ethereum/ethereum - sudo apt-get update - sudo apt-get install -y dpkg diff --git a/0 b/0 new file mode 100644 index 000000000..e69de29bb 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/common_functions.js b/CLI/commands/common/common_functions.js index fb3db68b7..7b21e555f 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 @@ -49,7 +49,7 @@ async function getGasLimit(options, action) { 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. + //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); @@ -153,10 +153,13 @@ module.exports = { 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) + }, 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/common/constants.js b/CLI/commands/common/constants.js index 30a3bf699..d121fd2da 100644 --- a/CLI/commands/common/constants.js +++ b/CLI/commands/common/constants.js @@ -29,7 +29,7 @@ module.exports = Object.freeze({ FUND_RAISE_TYPES: { ETH: 0, POLY: 1, - DAI: 2 + STABLE: 2 }, DEFAULT_BATCH_SIZE: 75, ADDRESS_ZERO: '0x0000000000000000000000000000000000000000' diff --git a/CLI/commands/common/permissions_list.js b/CLI/commands/common/permissions_list.js index 4d2b58cf7..8f74c15e7 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", @@ -70,36 +68,60 @@ function getPermissionList() { setAllowPrimaryIssuance: "ADMIN", changeHolderPercentage: "ADMIN" }, - LockupVolumeRestrictionTM: { - addLockup: "ADMIN", - addLockUpMulti: "ADMIN", - removeLockUp: "ADMIN", - modifyLockUp: "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" }, - 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" + 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", + }, + 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" } } } module.exports = { - verifyPermission: function(contractName, functionName) { + verifyPermission: function (contractName, functionName) { let list = getPermissionList(); try { return list[contractName][functionName] diff --git a/CLI/commands/dividends_manager.js b/CLI/commands/dividends_manager.js index 0f423bf5d..0b4dd8f39 100644 --- a/CLI/commands/dividends_manager.js +++ b/CLI/commands/dividends_manager.js @@ -1,492 +1,667 @@ -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 currentCheckpoint = await securityToken.methods.currentCheckpointId().call(); + if (currentCheckpoint > 0) { + console.log(`\nCurrent checkpoint: ${currentCheckpoint}`); + } - 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 options = ['Create checkpoint', 'Explore address balances']; + 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; } -} -async function start_explorer(){ - console.log('\n\x1b[34m%s\x1b[0m',"Dividends Manager - Main Menu"); + await executeApp(); +} - if (!tokenSymbol) - tokenSymbol = readlineSync.question('Enter the token symbol: '); +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!`)); +} - 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); +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); + } - // 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}`) - } + 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 currentCheckpoint = await securityToken.methods.currentCheckpointId().call(); - console.log(chalk.yellow(`\nToken is at checkpoint: ${currentCheckpoint}`)); + 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}`); + } +} - let options = ['Mint tokens', 'Transfer tokens', 'Create checkpoint', 'Set default exclusions for dividends', 'Tax holding settings', 'Create dividends'] +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; + } - if (currentCheckpoint > 0) { - options.push('Explore account at checkpoint', 'Explore total supply at checkpoint') - } + await dividendsManager(); +} - // Only show dividend options if divididenModule is already attached - if (await isDividendsModuleAttached()) { - options.push('Push dividends to accounts', - `Explore ${dividendsType} balance`, 'Reclaim expired dividends') - } +async function dividendsManager() { + console.log(chalk.blue(`Dividends module at ${currentDividendsModule.options.address}`), '\n'); - 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; - } - } - } - //Restart - await start_explorer(); -} + 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(); -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); + console.log(`- Wallet: ${wallet}`); + console.log(`- Current dividends: ${currentDividends.length}`); + console.log(`- Default exclusions: ${defaultExcluded.length}`); - 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.")); - } + let options = ['Change wallet', 'Create checkpoint']; + if (currentCheckpointId > 0) { + options.push('Explore checkpoint'); } -} - -async function transferTokens(address, amount){ - await whitelistAddress(address); + 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'); - 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 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 'Change wallet': + await changeWallet(); + break; + case 'Create checkpoint': + await createCheckpointFromDividendModule(); + break; + case 'Explore checkpoint': + await exploreCheckpoint(); + 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; } -} -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)`); + await dividendsManager(); +} - 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 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 exploreTotalSupply(checkpoint){ - let totalSupply = await securityToken.methods.totalSupply().call(); - totalSupply = web3.utils.fromWei(totalSupply); - console.log(`TotalSupply is: ${totalSupply} (Using totalSupply)`); +async function createCheckpointFromDividendModule() { + let createCheckpointAction = securityToken.methods.createCheckpoint(); + await common.sendTransaction(createCheckpointAction); + console.log(chalk.green(`Checkpoint have been created successfully!`)); +} - let totalSupplyAt = await securityToken.methods.totalSupplyAt(checkpoint).call(); - totalSupplyAt = web3.utils.fromWei(totalSupplyAt); - console.log(`TotalSupply is: ${totalSupplyAt} (Using totalSupplyAt - checkpoint ${checkpoint})`); +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() { - 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.`)); - showExcluded(event._excluded); + 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 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')}`); + 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(`- 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: ${claimedInvestors} (${investorArray.length - excludedInvestors !== 0 ? claimedInvestors / (investorArray.length - excludedInvestors) * 100 : 0}%)`); + console.log(` Excluded: ${excludedInvestors} `); + // ------------------ + + + 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 'Return to main menu': + case 'Explore account': + await exploreAccount(dividendIndex, dividendTokenAddress, dividendTokenSymbol); break; + 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(); + await manageExistingDividend(dividendIndex); +} - 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 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 (err) { + 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(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) { + let receipt = await common.sendTransaction(createDividendAction, { value: web3.utils.toWei(dividendAmountBN) }); + let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, 'EtherDividendDeposited'); console.log(` - Failed to claim ${web3.utils.fromWei(event._amount)} ${dividendsType} - to account ${event._payee}` +Dividend ${ event._dividendIndex} deposited` ); } } - - 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 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'; +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' + ]); } - let event = common.getEventFromLogs(currentDividendsModule._jsonInterface, receipt.logs, eventName); - console.log(` - Reclaimed Amount ${web3.utils.fromWei(event._claimedAmount)} ${dividendsType} - to account ${event._claimer}` - ); + console.log(); + console.log(table(dataTable)); } -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}.`)); +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 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 withheldPercentage = (!excluded) ? (withheld !== '0' ? parseFloat(withheld) / parseFloat(amount) * 100 : 0) : 'NA'; + let received = !excluded ? web3.utils.fromWei(_amountArray[i]) : 0; + 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(); + 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(); } -// 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 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 isDividendsModuleAttached() { - let dividendsModuleName; - if (dividendsType == 'POLY') { - dividendsModuleName = 'ERC20DividendCheckpoint'; - } else if (dividendsType == 'ETH') { - dividendsModuleName = 'EtherDividendCheckpoint'; - } +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); - 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(); + 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} `); } - currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, dividendsModuleAddress); - currentDividendsModule.setProvider(web3.currentProvider); } + 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.`)); +} - return (typeof currentDividendsModule !== 'undefined'); +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)} ${dividendTokenSymbol} +to account ${ event._claimer} ` + ); } 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 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 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 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 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(`Module deployed at address: ${event._module}`); - currentDividendsModule = new web3.eth.Contract(dividendsModuleABI, event._module); - currentDividendsModule.setProvider(web3.currentProvider); + console.log(chalk.green(`Module deployed at address: ${event._module} `)); } } -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. +// Helper functions +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); + } +} + +function logPushResults(receipt) { + let successEventName; + if (dividendsType == 'ERC20') { + successEventName = 'ERC20DividendClaimed'; } - options = options.concat(checkpoints); + 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')); + } + } + 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) { + 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() { let result = []; - + let checkPointsTimestamps = await securityToken.methods.getCheckpointTimes().call(); for (let index = 0; index < checkPointsTimestamps.length; index++) { let checkpoint = {}; @@ -498,91 +673,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; +} - 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); - } - } +function isExpiredDividend(dividend) { + let now = Math.floor(Date.now() / 1000); + return now > dividend.expiry; +} + +function hasRemaining(dividend) { + return Number(new web3.utils.BN(dividend.amount).sub(new web3.utils.BN(dividend.claimedAmount))).toFixed(10) > 0; +} + +function hasRemainingWithheld(dividend) { + return Number(new web3.utils.BN(dividend.dividendWithheld).sub(new web3.utils.BN(dividend.dividendWithheldReclaimed))).toFixed(10) > 0; +} - if (dividends.length > 0) { - let options = dividends.map(function(d) { - return `${web3.utils.toAscii(d.name)} +async function selectDividend(dividends) { + let result = null; + let options = dividends.map(function (d) { + return `${d.name} + 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')} - 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}` - }); + Expiry: ${moment.unix(d.expiry).format('MMMM Do YYYY, HH:mm:ss')} ` + }); - 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`)) + 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('./CLI/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/commands/helpers/contract_abis.js b/CLI/commands/helpers/contract_abis.js index 8a551b70b..b6abc7316 100644 --- a/CLI/commands/helpers/contract_abis.js +++ b/CLI/commands/helpers/contract_abis.js @@ -8,8 +8,11 @@ let cappedSTOABI; let usdTieredSTOABI; let generalTransferManagerABI; let manualApprovalTransferManagerABI; +let blacklistTransferManagerABI; let countTransferManagerABI; let percentageTransferManagerABI; +let lockUpTransferManagerABI; +let volumeRestrictionTMABI; let generalPermissionManagerABI; let polyTokenABI; let cappedSTOFactoryABI; @@ -21,31 +24,36 @@ 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; - 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; + 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; + 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; @@ -82,12 +90,21 @@ module.exports = { manualApprovalTransferManager: function () { return manualApprovalTransferManagerABI; }, + blacklistTransferManager: function () { + return blacklistTransferManagerABI; + }, countTransferManager: function () { return countTransferManagerABI; }, percentageTransferManager: function () { return percentageTransferManagerABI; }, + lockUpTransferManager: function () { + return lockUpTransferManagerABI; + }, + volumeRestrictionTM: function () { + return volumeRestrictionTMABI; + }, generalPermissionManager: function () { return generalPermissionManagerABI; }, @@ -120,5 +137,8 @@ module.exports = { }, moduleFactory: function () { return moduleFactoryABI; + }, + erc20: function () { + return erc20ABI; } -} \ No newline at end of file +} 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/investor_portal.js b/CLI/commands/investor_portal.js index cdfa66828..d59fd4bac 100644 --- a/CLI/commands/investor_portal.js +++ b/CLI/commands/investor_portal.js @@ -9,12 +9,15 @@ var gbl = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); +const ETH = 'ETH'; +const POLY = 'POLY'; +const STABLE = 'STABLE'; + let securityTokenRegistry; let securityToken; let selectedSTO; let currentSTO; let polyToken; -let usdToken; let generalTransferManager; let raiseTypes = []; @@ -55,17 +58,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) @@ -87,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.`)); @@ -152,17 +152,22 @@ async function showTokenInfo() { // Show info async function showUserInfo(_user) { + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); + 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)) { - console.log(` - DAI balance:\t ${await usdBalance(_user)}`); + if (await currentSTO.methods.fundRaiseTypes(gbl.constants.FUND_RAISE_TYPES.STABLE).call()) { + let stableSymbolsAndBalance = await processAddressWithBalance(listOfStableCoins); + stableSymbolsAndBalance.forEach(stable => { + console.log(` - ${stable.symbol} balance:\t ${web3.utils.fromWei(stable.balance)}`); + }); } } @@ -235,16 +240,63 @@ 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) { + let symbol = await checkSymbol(address); + list.push({ "symbol": symbol, "address": address }) + } + 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 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 = []; + 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()) { + 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 stable coin(s): ${displayInvestorInvested} USD`); + } else { + console.log(` - Invested in ${fundType}:\t ${displayInvestorInvested} ${fundType}`); + } } } 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; @@ -253,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`); @@ -277,10 +330,15 @@ 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 = []; + 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()) { raiseTypes.push(fundType); + if (fundType == STABLE) { + stableSymbols = await processAddress(listOfStableCoins) + } } } @@ -310,8 +368,13 @@ async function showUSDTieredSTOInfo() { let mintedPerTier = mintedPerTierPerRaiseType[gbl.constants.FUND_RAISE_TYPES[type]]; - displayMintedPerTierPerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + displayMintedPerTierPerType += ` + Sold for stable coin(s): ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } else { + displayMintedPerTierPerType += ` Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } } displayTiers += ` @@ -331,18 +394,34 @@ 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 += ` + if ((type == STABLE) && (stableSymbols.length)) { + 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}`; - + } //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 stable coin(s): ${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.map((obj) => { return obj.symbol }).toString().replace(`,`, ` - `)}` + } let now = Math.floor(Date.now() / 1000); let timeTitle; @@ -375,7 +454,7 @@ async function showUSDTieredSTOInfo() { - Investor count: ${displayInvestorCount} - Funds Raised` + displayFundsRaisedPerType + ` - USD: ${displayFundsRaisedUSD} USD + Total USD: ${displayFundsRaisedUSD} USD `); if (!displayCanBuy) { @@ -393,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)) { @@ -439,7 +522,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`)); @@ -450,14 +537,30 @@ 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 ${type} price:\t\t ${displayPrice} USD`)); + } } if (raiseTypes.length > 1) { - let index = readlineSync.keyInSelect(raiseTypes, 'Choose one of the allowed raise types: ', { cancel: false }); - raiseType = raiseTypes[index]; + const stableIndex = raiseTypes.indexOf(STABLE); + if (stableIndex > -1) { + raiseTypes.splice(stableIndex, 1) + stableSymbols.forEach((stable) => { + raiseTypes.push(stable.symbol) + }) + } + 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(''); + } } } @@ -465,7 +568,14 @@ 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)); @@ -479,7 +589,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.`)); @@ -487,7 +604,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(); @@ -503,19 +620,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(); } @@ -529,13 +651,12 @@ async function investUsdTieredSTO(currency, amount) { await showUserInfoForUSDTieredSTO(); } -async function polyBalance(_user) { - let balance = await polyToken.methods.balanceOf(_user).call(); - return web3.utils.fromWei(balance); +function selectToken(msg) { + return readlineSync.keyInSelect(raiseTypes, msg, { cancel: false }); } -async function usdBalance(_user) { - let balance = await usdToken.methods.balanceOf(_user).call(); +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 4f19df76b..f581b7339 100644 --- a/CLI/commands/sto_manager.js +++ b/CLI/commands/sto_manager.js @@ -5,11 +5,13 @@ 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'; /////////////////// // 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 @@ -44,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': @@ -59,7 +61,7 @@ async function executeApp() { case 'Add new STO module': await addSTOModule(); break; - case 'Exit': + case 'EXIT': exit = true; break; } @@ -96,6 +98,7 @@ async function showSTO(selectedSTO, currentSTO) { break; case 'USDTieredSTO': await usdTieredSTO_status(currentSTO); + await showAccreditedData(currentSTO); break; } } @@ -125,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; } @@ -270,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}`)); } //////////////////// @@ -280,7 +281,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')) { @@ -289,53 +290,110 @@ 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) { - let addresses = {}; +async function addressesConfigUSDTieredSTO(usdTokenRaise) { - 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 { - if (usdTokenRaise) { - addresses.usdToken = readlineSync.question('Enter the address of the USD Token or stable coin (' + usdToken.options.address + '): ', { + 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: usdToken.options.address + defaultInput: Issuer.address }); - if (addresses.usdToken == "") addresses.usdToken = usdToken.options.address; - } else { - addresses.usdToken = '0x0000000000000000000000000000000000000000'; - } + 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; + + 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) { + 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 = [] + 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(",") + } + + } while (menu); 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": symbol, "address": address }) + } + return list +} + function tiersConfigUSDTieredSTO(polyRaise) { let tiers = {}; @@ -484,7 +542,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); @@ -521,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(); @@ -529,12 +588,16 @@ 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(); + let listOfStableCoins = await currentSTO.methods.getUsdTokens().call(); 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); } } @@ -564,8 +627,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 stable coin(s): ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } else { + displayMintedPerTierPerType += ` + Sold for ${type}:\t\t ${web3.utils.fromWei(mintedPerTier)} ${displayTokenSymbol} ${displayDiscountMinted}`; + } } displayTiers += ` @@ -588,29 +656,62 @@ 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()); - displayWalletBalancePerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + 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)`; + } 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)) { + 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)`; + } let fundsRaised = web3.utils.fromWei(await currentSTO.methods.fundsRaised(gbl.constants.FUND_RAISE_TYPES[type]).call()); - displayFundsRaisedPerType += ` + if ((type == STABLE) && (stableSymbols.length)) { + 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}`; + } //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 stable coin(s): ${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.map((obj) => { return obj.symbol }).toString().replace(`,`, ` - `)}` + } let now = Math.floor(Date.now() / 1000); let timeTitle; @@ -650,10 +751,21 @@ async function usdTieredSTO_status(currentSTO) { - Investor count: ${displayInvestorCount} - Funds Raised` + displayFundsRaisedPerType + ` - USD: ${displayFundsRaisedUSD} USD + Total USD: ${displayFundsRaisedUSD} USD `); +} + +async function checkStableBalance(walletAddress, stableAddress) { + let stableCoin = common.connect(abis.erc20(), stableAddress); + try { + return await stableCoin.methods.balanceOf(walletAddress).call(); + } catch (e) { + return "" + } +} - 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 getStableCoinsRaised(currentSTO, address) { + return await currentSTO.methods.stableCoinsRaised(address).call() } async function usdTieredSTO_configure(currentSTO) { @@ -676,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) { @@ -690,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]; @@ -699,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]; @@ -710,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; @@ -737,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 @@ -758,7 +898,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`); @@ -785,8 +925,9 @@ 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 = 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`); @@ -812,7 +953,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); } @@ -837,7 +978,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(); } } @@ -861,7 +1002,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(); } @@ -939,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: '); @@ -965,4 +1106,4 @@ module.exports = { await initialize(_tokenSymbol); return addSTOModule(stoConfig) } -} \ No newline at end of file +} diff --git a/CLI/commands/strMigrator.js b/CLI/commands/strMigrator.js index 4a8dabfe0..7d4e0248f 100644 --- a/CLI/commands/strMigrator.js +++ b/CLI/commands/strMigrator.js @@ -54,7 +54,7 @@ async function step_instance_toSTR(toStrAddress) { // return web3.utils.isAddress(input); // }, // limitMessage: "Must be a valid address" - // }); + // }); _toStrAddress = "0x240f9f86b1465bf1b8eb29bc88cbf65573dfdd97"; } @@ -81,7 +81,7 @@ async function step_instance_fromTR(fromTrAddress) { // return web3.utils.isAddress(input); // }, // limitMessage: "Must be a valid address" - // }); + // }); _fromTrAddress = "0xc31714e6759a1ee26db1d06af1ed276340cd4233"; } @@ -192,7 +192,7 @@ async function step_instance_fromSTR(fromStrAddress) { // return web3.utils.isAddress(input); // }, // limitMessage: "Must be a valid address" - // }); + // }); _fromStrAddress = "0xef58491224958d978facf55d2120c55a24516b98"; } @@ -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,9 +230,9 @@ 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 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'); @@ -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..fbe89b38f 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`); diff --git a/CLI/commands/transfer_manager.js b/CLI/commands/transfer_manager.js index 16af0e34e..39af92b78 100644 --- a/CLI/commands/transfer_manager.js +++ b/CLI/commands/transfer_manager.js @@ -6,12 +6,45 @@ 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 WHITELIST_DATA_CSV = `${__dirname}/../data/Transfer/GTM/whitelist_data.csv`; +const ADD_BLACKLIST_DATA_CSV = `${__dirname}/../data/Transfer/BlacklistTM/add_blacklist_data.csv`; +const MODIFY_BLACKLIST_DATA_CSV = `${__dirname}/../data/Transfer/BlacklistTM/modify_blacklist_data.csv`; +const DELETE_BLACKLIST_DATA_CSV = `${__dirname}/../data/Transfer/BlacklistTM/delete_blacklist_data.csv`; +const ADD_INVESTOR_BLACKLIST_DATA_CSV = `${__dirname}/../data/Transfer/BlacklistTM/add_investor_blacklist_data.csv`; +const REMOVE_INVESTOR_BLACKLIST_DATA_CSV = `${__dirname}/../data/Transfer/BlacklistTM/remove_investor_blacklist_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 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_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']; + +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'; // App flow let tokenSymbol; @@ -21,98 +54,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 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 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 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() { @@ -121,8 +152,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': @@ -181,14 +212,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': @@ -211,23 +246,20 @@ async function configExistingModules(tmModules) { currentTransferManager.setProvider(web3.currentProvider); await percentageTransferManager(); 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. - *********************************` - )); + 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); + await blacklistTransferManager(); break; - case 'LookupVolumeRestrictionTM': - //await lookupVolumeRestrictionTM(); - console.log(chalk.red(` - ********************************* - This option is not yet available. - *********************************` - )); + case 'VolumeRestrictionTM': + currentTransferManager = new web3.eth.Contract(abis.volumeRestrictionTM(), tmModules[index].address); + currentTransferManager.setProvider(web3.currentProvider); + await volumeRestrictionTM(); break; } } @@ -240,7 +272,7 @@ async function addTransferManagerModule() { 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' }); + 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]) { @@ -260,56 +292,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); @@ -320,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(); @@ -372,9 +354,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 *****'); @@ -412,10 +394,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); @@ -514,7 +496,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) { @@ -532,17 +518,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]) && @@ -559,7 +555,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('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`); @@ -567,228 +563,446 @@ 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 totalApprovals = await currentTransferManager.methods.getTotalApprovalsLength().call(); + console.log(`- Current active approvals: ${totalApprovals}`); - let options = ['Check manual approval', 'Add manual approval', 'Revoke manual approval', - 'Check manual blocking', 'Add manual blocking', 'Revoke manual blocking']; + 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; - 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.`)); - } + case MATM_MENU_MANAGE: + await matmManage(); 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' }); - 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.`)); + 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; + } } + } + } 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 getManualApproval(_from, _to) { - let result = null; +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 manualApproval = await currentTransferManager.methods.manualApprovals(_from, _to).call(); - if (manualApproval.expiryTime !== "0") { - result = manualApproval; + 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); } - return result; + 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 getManualBlocking(_from, _to) { - let result = null; +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 manualBlocking = await currentTransferManager.methods.manualBlockings(_from, _to).call(); - if (manualBlocking !== "0") { - result = manualBlocking; + 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); } - return result; + 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 countTransferManager() { - console.log(chalk.blue(`Count Transfer Manager at ${currentTransferManager.options.address}`), '\n'); +async function matmManageTimeOrDescription(selectedApproval) { + let { expiryTime, description } = readExpiryTimeAndDescription(selectedApproval); - // Show current data - let displayMaxHolderCount = await currentTransferManager.methods.maxHolderCount().call(); + 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!`)); +} - console.log(`- Max holder count: ${displayMaxHolderCount}`); +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 }; +} - 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 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; } } -async function percentageTransferManager() { - console.log(chalk.blue(`Percentage Transfer Manager at ${currentTransferManager.options.address}`), '\n'); +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`); +} - // Show current data - let displayMaxHolderPercentage = await currentTransferManager.methods.maxHolderPercentage().call(); - let displayAllowPrimaryIssuance = await currentTransferManager.methods.allowPrimaryIssuance().call(); +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; + } - console.log(`- Max holder percentage: ${fromWeiPercentage(displayMaxHolderPercentage)}%`); - console.log(`- Allow primary issuance: ${displayAllowPrimaryIssuance ? `YES` : `NO`}`); + 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; +} - 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'); +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 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); - }, + + 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.getApprovalDetails(_from, _to).call(); + if ((manualApproval[0] >= new Date()) && (manualApproval[1] != 0)) { + result = manualApproval; + } + return result; +} + +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); +} + +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 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() { + console.log('\n', 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 = 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: '); + 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; + case 'RETURN': + return; + } + + await countTransferManager(); +} + +async function percentageTransferManager() { + console.log('\n', 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 = 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: ', { + 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); @@ -799,256 +1013,1589 @@ async function percentageTransferManager() { case 'Check if investor is whitelisted': let investorToCheck = readlineSync.question('Enter the address of the investor: ', { limit: function (input) { - return web3.utils.isAddress(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': + 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': + 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; + } + + await percentageTransferManager(); +} + +async function blacklistTransferManager() { + 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}`); + + let options = ['Add new blacklist']; + if (currentBlacklists.length > 0) { + options.push('Manage existing blacklist', 'Explore account'); + } + 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 '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) { + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); + }, + limitMessage: `All addresses must be valid` + }).split(','); + let deleteInvestorFromAllBlacklistAction; + if (investorsToRemove.length === 1) { + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklist(investorsToRemove[0]); + } else { + deleteInvestorFromAllBlacklistAction = currentTransferManager.methods.deleteInvestorFromAllBlacklistMulti(investorsToRemove); + } + 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(currentBlacklists); + break; + case 'RETURN': + return; + } + + await blacklistTransferManager(); +} + +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(); + 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: ${(currentBlacklist.endTime - currentBlacklist.startTime) / 60 / 60 / 24} 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) { + return (input !== '' && input.split(",").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": + 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'); + console.log(chalk.green(`${web3.utils.hexToUtf8(deleteBlacklistTypeEvent._blacklistName)} blacklist type has been deleted successfully!`)); + } + return; + case 'RETURN': + return; + } + + await manageExistingBlacklist(blacklistName); +} + +async function operateWithMultipleBlacklists(currentBlacklists) { + 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': + 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 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'); + 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`); + } + + 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() { + 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`); + } +} + +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 + }); + 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 volumeRestrictionTM() { + console.log('\n', chalk.blue(`Volume Restriction Transfer Manager at ${currentTransferManager.options.address}`, '\n')); + + 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: ${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 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(); + console.log(`- Individual restrictions: ${addressesAndRestrictions.allAddresses.length}`); + let exemptedAddresses = await currentTransferManager.methods.getExemptAddress().call(); + console.log(`- Exempted addresses: ${exemptedAddresses.length}`); + + let options = []; + 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', + '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 restrictions': + showRestrictionTable( + addressesAndRestrictions.allAddresses, + addressesAndRestrictions.allowedTokens, + addressesAndRestrictions.typeOfRestriction, + addressesAndRestrictions.rollingPeriodInDays, + addressesAndRestrictions.startTime, + addressesAndRestrictions.endTime, + ); + break; + case 'Show exempted addresses': + showExemptedAddresses(exemptedAddresses); + break; + case 'Change exempt wallet': + await changeExemptWallet(); + break; + case 'Change default restrictions': + await changeDefaultRestrictions(hasGlobalDailyRestriction, hasGlobalCustomRestriction); + 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(); +} + +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)); +} + +function showExemptedAddresses(addresses) { + console.log("*********** Exepmpted addresses ***********"); + addresses.map(i => console.log(i)); +} + +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(hasGlobalDailyRestriction, hasGlobalCustomRestriction) { + let options = []; + if (!hasGlobalDailyRestriction) { + options.push('Add global daily restriction'); + } else { + options.push('Modify global daily restriction', 'Remove global daily restriction'); + } + + if (!hasGlobalCustomRestriction) { + options.push('Add global custom restriction'); + } else { + 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 global daily restriction': + let globalDailyRestrictoToAdd = inputRestrictionData(true); + let addGlobalDailyRestrictionAction = currentTransferManager.methods.addDefaultDailyRestriction( + globalDailyRestrictoToAdd.allowedTokens, + globalDailyRestrictoToAdd.startTime, + globalDailyRestrictoToAdd.endTime, + globalDailyRestrictoToAdd.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 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 addGlobalCustomRestrictionAction = currentTransferManager.methods.addDefaultRestriction( + globalCustomRestrictoToAdd.allowedTokens, + globalCustomRestrictoToAdd.startTime, + globalCustomRestrictoToAdd.rollingPeriodInDays, + globalCustomRestrictoToAdd.endTime, + globalCustomRestrictoToAdd.restrictionType + ); + 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 modifiyGlobalCustomRestrictionAction = currentTransferManager.methods.modifyDefaultRestriction( + globalCustomRestrictoToModify.allowedTokens, + globalCustomRestrictoToModify.startTime, + globalCustomRestrictoToModify.rollingPeriodInDays, + globalCustomRestrictoToModify.endTime, + globalCustomRestrictoToModify.restrictionType + ); + 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': + 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; + } +} + +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 currentCustomRestriction = await currentTransferManager.methods.individualRestriction(holder).call(); + let hasCustomRestriction = parseInt(currentCustomRestriction.startTime) !== 0; + + console.log(`*** Current individual 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(`- 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)}%`}`); + 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 = []; + if (!hasDailyRestriction) { + options.push('Add individual daily restriction'); + } else { + options.push('Modify individual daily restriction', 'Remove individual daily restriction'); + } + + if (!hasCustomRestriction) { + options.push('Add individual custom restriction'); + } else { + options.push('Modify individual custom restriction', 'Remove individual 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 individual daily restriction': + let dailyRestrictonToAdd = inputRestrictionData(true); + let addDailyRestrictionAction = currentTransferManager.methods.addIndividualDailyRestriction( + holder, + 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 dailyRestrictonToModify = inputRestrictionData(true); + let modifyDailyRestrictionAction = currentTransferManager.methods.modifyIndividualDailyRestriction( + holder, + dailyRestrictonToModify.allowedTokens, + dailyRestrictonToModify.startTime, + dailyRestrictonToModify.endTime, + dailyRestrictonToModify.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 custom restriction': + let restrictonToAdd = inputRestrictionData(false); + let addCustomRestrictionAction = currentTransferManager.methods.addIndividualRestriction( + holder, + restrictonToAdd.allowedTokens, + restrictonToAdd.startTime, + restrictonToAdd.rollingPeriodInDays, + restrictonToAdd.endTime, + restrictonToAdd.restrictionType + ); + 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 custom restriction': + let restrictonToModify = inputRestrictionData(false); + let modifyCustomRestrictionAction = currentTransferManager.methods.modifyIndividualRestriction( + holder, + restrictonToModify.allowedTokens, + restrictonToModify.startTime, + restrictonToModify.rollingPeriodInDays, + restrictonToModify.endTime, + restrictonToModify.restrictionType + ); + 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 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; + } +} + +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 appliyngDailyRestriction = null; + let applyingCustomRestriction = null; + let hasIndividualRestrictions = false; + let isExempted = await currentTransferManager.methods.exemptList(account).call(); + if (!isExempted) { + let individuallDailyRestriction = await currentTransferManager.methods.individualDailyRestriction(account).call(); + if (parseInt(individuallDailyRestriction.endTime) !== 0) { + appliyngDailyRestriction = individuallDailyRestriction; + } + let customRestriction = await currentTransferManager.methods.individualRestriction(account).call(); + if (parseInt(customRestriction.endTime) !== 0) { + applyingCustomRestriction = customRestriction; + } + + hasIndividualRestrictions = applyingCustomRestriction || appliyngDailyRestriction; + + if (!hasIndividualRestrictions) { + let globalDailyRestriction = await currentTransferManager.methods.defaultDailyRestriction().call(); + if (parseInt(globalDailyRestriction.endTime) !== 0) { + appliyngDailyRestriction = globalDailyRestriction; + } + 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: ${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: ${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 (applyingCustomRestriction || appliyngDailyRestriction) { + 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', + '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 addCustomRestrictionsInBatch(); + break; + case 'Modify multiple individual restrictions': + await modifyCustomRestrictionsInBatch(); + break; + case 'Remove multiple individual restrictions': + await removeCustomRestrictionsInBatch(); + 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 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) { + 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 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 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 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) { + 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 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 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 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) { + 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 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 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`); + } +} + +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.question(`Enter the maximum amount of tokens allowed to be traded every ${isDaily ? 'day' : 'rolling period'}: `).toString()); + } else { + 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; + } 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 month 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 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: "Must be a valid address" + limitMessage: `Invalid lockup name` }); - let isWhitelisted = await currentTransferManager.methods.whitelist(investorToCheck).call(); - if (isWhitelisted) { - console.log(chalk.green(`${investorToCheck} is whitelisted!`)); + 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 { - console.log(chalk.yellow(`${investorToCheck} is not whitelisted!`)); + 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 '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: ', { + 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 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!`)); + 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.green(`${modifyWhitelistEvent._investor} has been removed from the whitelist sucessfully!`)); - } - 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`); + console.log(chalk.yellow(`The address ${investorToExplore} has no lockups`)); } 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!`)); - } + case 'Operate with multiple lockups': + await operateWithMultipleLockups(currentLockups); break; - + case 'RETURN': + return; } + + await lockUpTransferManager(); } -async function singleTradeVolumeRestrictionTM() { - console.log(chalk.blue(`Single Trade Volume Restriction Transfer Manager at ${currentTransferManager.options.address} `)); - console.log(); +async function manageExistingLockups(lockupName) { + console.log('\n', chalk.blue(`Lockup ${web3.utils.hexToUtf8(lockupName)}`), '\n'); // 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(); + let currentLockup = await currentTransferManager.methods.getLockUp(lockupName).call(); + let investors = await currentTransferManager.methods.getListOfAddresses(lockupName).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(`- 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 = []; - 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 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 = 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': - let disallowPrimaryIssuanceAction = currentTransferManager.methods.setAllowPrimaryIssuance(!displayAllowPrimaryIssuance); - await common.sendTransaction(disallowPrimaryIssuanceAction); + 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 '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!`)); + 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 'Remove exempted wallet': - let exemptedWallet = readlineSync.question('Enter the wallet to remove from exempt: ', { + 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 web3.utils.isAddress(input); + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); }, - 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!`)); + 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 '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: ', { + 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 (parseInt(input) > 0 && parseInt(input) <= 100); + return (input !== '' && input.split(",").every(a => web3.utils.isAddress(a))); }, - 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)} % `)); + 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 '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} `)); + 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 '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)} % `)); + case 'Modify multiple lockups': + await modifyLockupsInBatch(); 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} `)); + case 'Delete multiple lockups': + await deleteLockupsInBatch(); 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`)); + case 'Add lockups to multiple investors': + await addLockupsToInvestorsInBatch(); 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`)); + 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) { @@ -1066,11 +2613,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) { @@ -1092,7 +2639,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(); } @@ -1159,13 +2706,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 +2725,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 = { @@ -1194,6 +2741,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/Checkpoint/exclusions_data.csv b/CLI/data/Checkpoint/exclusions_data.csv new file mode 100644 index 000000000..406cd94cf --- /dev/null +++ b/CLI/data/Checkpoint/exclusions_data.csv @@ -0,0 +1,5 @@ +0xee7ae74d964f2be7d72c1b187b38e2ed3615d4d1 +0x49fc0b78238dab644698a90fa351b4c749e123d2 +0x10223927009b8add0960359dd90d1449415b7ca9 +0x3c65cfe3de848cf38e9d76e9c3e57a2f1140b399 +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98 \ No newline at end of file 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 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 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/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/CLI/data/Transfer/MATM/add_manualapproval_data.csv b/CLI/data/Transfer/MATM/add_manualapproval_data.csv new file mode 100644 index 000000000..48d5f2a54 --- /dev/null +++ b/CLI/data/Transfer/MATM/add_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/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 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 diff --git a/CLI/data/Transfer/VRTM/add_custom_restriction_data.csv b/CLI/data/Transfer/VRTM/add_custom_restriction_data.csv new file mode 100644 index 000000000..1807e90e6 --- /dev/null +++ b/CLI/data/Transfer/VRTM/add_custom_restriction_data.csv @@ -0,0 +1,8 @@ +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/add_daily_restriction_data.csv b/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv new file mode 100644 index 000000000..1486579b7 --- /dev/null +++ b/CLI/data/Transfer/VRTM/add_daily_restriction_data.csv @@ -0,0 +1,8 @@ +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/modify_custom_restriction_data.csv b/CLI/data/Transfer/VRTM/modify_custom_restriction_data.csv new file mode 100644 index 000000000..b69f43361 --- /dev/null +++ b/CLI/data/Transfer/VRTM/modify_custom_restriction_data.csv @@ -0,0 +1,5 @@ +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 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..908c164e9 --- /dev/null +++ b/CLI/data/Transfer/VRTM/modify_daily_restriction_data.csv @@ -0,0 +1,5 @@ +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/remove_custom_restriction_data.csv b/CLI/data/Transfer/VRTM/remove_custom_restriction_data.csv new file mode 100644 index 000000000..d927ee57b --- /dev/null +++ b/CLI/data/Transfer/VRTM/remove_custom_restriction_data.csv @@ -0,0 +1,2 @@ +0xabf60de3265b3017db7a1be66fc8b364ec1dbb98 +0xb841fe5a89da1bbef2d0805fbd7ffcbbb2fca5e3 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/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..c46425716 100644 --- a/CLI/polymath-cli.js +++ b/CLI/polymath-cli.js @@ -12,7 +12,7 @@ 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 time = require('./commands/helpers/time'); const gbl = require('./commands/common/global'); const program = require('commander'); const moment = require('moment'); @@ -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 @@ -155,7 +162,7 @@ program await permission_manager.executeApp(); }); -program + program .command('time_travel') .alias('tt') .option('-p, --period ', 'Period of time in seconds to increase') @@ -172,7 +179,6 @@ program await time.increaseTimeToEpochDate(cmd.toEpochTime); } }); - program.parse(process.argv); if (typeof program.commands.length == 0) { 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 diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 5c538d583..d90527993 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -103,7 +103,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); @@ -120,14 +120,14 @@ 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")) { + if (ISecurityTokenRegistry(getAddressValue(Encoder.getKey("securityTokenRegistry"))).isSecurityToken(msg.sender)) { + if (IFeatureRegistry(getAddressValue(Encoder.getKey("featureRegistry"))).getFeatureStatus("customModulesAllowed")) { require( - getBool(Encoder.getKey("verified", _moduleFactory)) || IOwnable(_moduleFactory).owner() == IOwnable(msg.sender).owner(), + 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); @@ -149,7 +149,7 @@ 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" @@ -157,7 +157,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } 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; @@ -185,14 +185,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]; @@ -224,7 +224,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); } @@ -307,16 +307,16 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) public view returns(address[] memory) { 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( + 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( + 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++; } } @@ -324,7 +324,7 @@ 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( + if (IOwnable(_addressList[j]).owner() == IOwnable(_securityToken).owner() || getBoolValue( Encoder.getKey("verified", _addressList[j]) )) { if (_isCompatibleModule(_addressList[j], _securityToken)) { @@ -332,7 +332,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { 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++; @@ -375,7 +375,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")); @@ -396,7 +396,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")); } /** @@ -404,6 +404,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/STRGetter.sol b/contracts/STRGetter.sol index 31df84bdb..29d5264fd 100644 --- a/contracts/STRGetter.sol +++ b/contracts/STRGetter.sol @@ -24,7 +24,7 @@ contract STRGetter is EternalStorage { for (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 || getTickerStatus(ticker)) { + if (getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || getTickerStatus(ticker)) { counter ++; } } @@ -33,7 +33,7 @@ contract STRGetter is EternalStorage { for (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 || getTickerStatus(ticker)) { + if (getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || getTickerStatus(ticker)) { tempList[counter] = tickers[i]; counter ++; } @@ -74,7 +74,7 @@ contract STRGetter is 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 (_allTokens || IOwnable(token).owner() == _owner) { count = count + 1; @@ -87,7 +87,7 @@ contract STRGetter is 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 (_allTokens || IOwnable(token).owner() == _owner) { result[index] = token; @@ -111,15 +111,15 @@ contract STRGetter is EternalStorage { function getTickerDetails(string calldata _ticker) external view returns (address, uint256, uint256, string memory, bool) { string memory ticker = Util.upper(_ticker); bool tickerStatus = getTickerStatus(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 ( getTickerOwner(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 { @@ -134,7 +134,7 @@ contract STRGetter is EternalStorage { */ function getSecurityTokenAddress(string calldata _ticker) external view returns (address) { string memory ticker = Util.upper(_ticker); - return getAddress(Encoder.getKey("tickerToSecurityToken", ticker)); + return getAddressValue(Encoder.getKey("tickerToSecurityToken", ticker)); } /** @@ -147,10 +147,10 @@ contract STRGetter is EternalStorage { */ function getSecurityTokenData(address _securityToken) external view returns (string memory, address, string memory, 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)) ); } @@ -158,14 +158,14 @@ contract STRGetter is EternalStorage { * @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[] memory) { - return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); + return VersionUtils.unpack(uint24(getUintValue(Encoder.getKey("latestVersion")))); } /** @@ -173,7 +173,7 @@ contract STRGetter is EternalStorage { * @return Fee amount */ function getSecurityTokenLaunchFee() public view returns(uint256) { - return getUint(STLAUNCHFEE); + return getUintValue(STLAUNCHFEE); } /** @@ -181,7 +181,7 @@ contract STRGetter is EternalStorage { * @return Fee amount */ function getTickerRegistrationFee() public view returns(uint256) { - return getUint(TICKERREGFEE); + return getUintValue(TICKERREGFEE); } /** @@ -189,16 +189,16 @@ contract STRGetter is EternalStorage { * @return Expiry limit */ function getExpiryLimit() public view returns(uint256) { - return getUint(EXPIRYLIMIT); + return getUintValue(EXPIRYLIMIT); } /** * @notice Gets the status of the ticker * @param _ticker Ticker whose status need to determine - * @return bool + * @return bool */ function getTickerStatus(string memory _ticker) public view returns(bool) { - return getBool(Encoder.getKey("registeredTickers_status", _ticker)); + return getBoolValue(Encoder.getKey("registeredTickers_status", _ticker)); } /** @@ -207,7 +207,7 @@ contract STRGetter is EternalStorage { * @return address Address of the owner */ function getTickerOwner(string memory _ticker) public view returns(address) { - return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + return getAddressValue(Encoder.getKey("registeredTickers_owner", _ticker)); } -} \ No newline at end of file +} diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index f8f6e010b..60c085e72 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -175,7 +175,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { external payable { - require(!getBool(INITIALIZE),"already initialized"); + require(!getBoolValue(INITIALIZE),"already initialized"); require( _STFactory != address(0) && _owner != address(0) && _polymathRegistry != address(0) && _getterContract != address(0), "Invalid address" @@ -201,13 +201,13 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { } function _updateFromRegistry() internal { - address polymathRegistry = getAddress(POLYMATHREGISTRY); + address polymathRegistry = getAddressValue(POLYMATHREGISTRY); set(POLYTOKEN, IPolymathRegistry(polymathRegistry).getAddress("PolyToken")); } /** * @notice Set the getter contract address - * @param _getterContract Address of the contract + * @param _getterContract Address of the contract */ function setGetterRegistry(address _getterContract) public onlyOwner { require(_getterContract != address(0)); @@ -215,7 +215,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { } function _implementation() internal view returns(address) { - return getAddress(Encoder.getKey("STRGetter")); + return getAddressValue(Encoder.getKey("STRGetter")); } ///////////////////////////// @@ -234,9 +234,9 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { require(_owner != address(0), "Owner should not be 0x"); require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); // Attempt to charge the reg fee if it is > 0 POLY - uint256 tickerFee = getUint(TICKERREGFEE); + uint256 tickerFee = getUintValue(TICKERREGFEE); 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) @@ -245,7 +245,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _deleteTickerOwnership(previousOwner, ticker); } /*solium-disable-next-line security/no-block-members*/ - _addTicker(_owner, ticker, _tokenName, now, now.add(getUint(EXPIRYLIMIT)), false, false, tickerFee); + _addTicker(_owner, ticker, _tokenName, now, now.add(getUintValue(EXPIRYLIMIT)), false, false, tickerFee); } /** @@ -260,7 +260,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { bool _status, bool _fromAdmin, uint256 _fee - ) + ) internal { _setTickerOwnership(_owner, _ticker); @@ -285,7 +285,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { uint256 _registrationDate, uint256 _expiryDate, bool _status - ) + ) external onlyOwner { @@ -307,7 +307,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { uint256 _registrationDate, uint256 _expiryDate, bool _status - ) + ) internal { address currentOwner = _tickerOwner(_ticker); @@ -319,13 +319,13 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { } // 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 memory _ticker) internal view returns(address) { - return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + return getAddressValue(Encoder.getKey("registeredTickers_owner", _ticker)); } /** @@ -351,7 +351,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { function _tickerAvailable(string memory _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; } @@ -359,7 +359,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { } function _tickerStatus(string memory _ticker) internal view returns(bool) { - return getBool(Encoder.getKey("registeredTickers_status", _ticker)); + return getBoolValue(Encoder.getKey("registeredTickers_status", _ticker)); } /** @@ -373,7 +373,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { 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); } @@ -389,19 +389,19 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { uint256 _expiryDate, string memory _tokenName, bool _status - ) + ) internal { bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); - if (getAddress(key) != _owner) set(key, _owner); + if (getAddressValue(key) != _owner) set(key, _owner); key = Encoder.getKey("registeredTickers_registrationDate", _ticker); - if (getUint(key) != _registrationDate) set(key, _registrationDate); + if (getUintValue(key) != _registrationDate) set(key, _registrationDate); key = Encoder.getKey("registeredTickers_expiryDate", _ticker); - if (getUint(key) != _expiryDate) set(key, _expiryDate); + if (getUintValue(key) != _expiryDate) set(key, _expiryDate); key = Encoder.getKey("registeredTickers_tokenName", _ticker); - if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) set(key, _tokenName); + if (Encoder.getKey(getStringValue(key)) != Encoder.getKey(_tokenName)) set(key, _tokenName); key = Encoder.getKey("registeredTickers_status", _ticker); - if (getBool(key) != _status) set(key, _status); + if (getBoolValue(key) != _status) set(key, _status); } /** @@ -413,9 +413,9 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { 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, + IOwnable(getAddressValue(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner" ); _deleteTickerOwnership(msg.sender, ticker); @@ -428,7 +428,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @notice Internal - Removes the owner of a ticker */ function _deleteTickerOwnership(address _owner, string memory _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); @@ -446,7 +446,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { */ 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); } @@ -466,31 +466,31 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { string calldata _ticker, string calldata _tokenDetails, bool _divisible - ) - external - whenNotPausedOrOwner + ) + external + whenNotPausedOrOwner { 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 = getUint(STLAUNCHFEE); + uint256 launchFee = getUintValue(STLAUNCHFEE); 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(getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))))).deployToken( + address newSecurityTokenAddress = ISTFactory(getAddressValue(Encoder.getKey("protocolVersionST", getUintValue(Encoder.getKey("latestVersion"))))).deployToken( _name, ticker, 18, _tokenDetails, msg.sender, _divisible, - getAddress(POLYMATHREGISTRY) + getAddressValue(POLYMATHREGISTRY) ); /*solium-disable-next-line security/no-block-members*/ @@ -516,26 +516,26 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { address _securityToken, string calldata _tokenDetails, uint256 _deployedAt - ) - external - onlyOwner + ) + 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"); 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; - expiryTime = registrationTime.add(getUint(EXPIRYLIMIT)); + expiryTime = registrationTime.add(getUintValue(EXPIRYLIMIT)); } set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); - emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getUint(STLAUNCHFEE)); + emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getUintValue(STLAUNCHFEE)); } /** @@ -558,7 +558,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @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("")); } ///////////////////////////// @@ -571,7 +571,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { */ 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); } @@ -598,7 +598,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @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); @@ -609,7 +609,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @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); @@ -650,11 +650,11 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _version[2] = _patch; uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); require( - VersionUtils.isValidVersion(VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))), _version), + VersionUtils.isValidVersion(VersionUtils.unpack(uint24(getUintValue(Encoder.getKey("latestVersion")))), _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); } /** @@ -671,7 +671,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @return bool */ function isPaused() public view returns(bool) { - return getBool(PAUSED); + return getBoolValue(PAUSED); } /** @@ -679,7 +679,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @return address owner */ function owner() public view returns(address) { - return getAddress(OWNER); + return getAddressValue(OWNER); } } diff --git a/contracts/interfaces/IBoot.sol b/contracts/interfaces/IBoot.sol index ecade0f31..9e295fb2f 100644 --- a/contracts/interfaces/IBoot.sol +++ b/contracts/interfaces/IBoot.sol @@ -6,4 +6,4 @@ interface IBoot { * @return bytes4 Configure function signature */ function getInitFunction() external pure returns(bytes4); -} +} \ No newline at end of file diff --git a/contracts/interfaces/ICheckPermission.sol b/contracts/interfaces/ICheckPermission.sol new file mode 100644 index 000000000..2e14fa5b9 --- /dev/null +++ b/contracts/interfaces/ICheckPermission.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.5.0; + +interface ICheckPermission { + /** + * @notice Validate permissions with PermissionManager if it exists, If no Permission return false + * @dev Note that IModule withPerm will allow ST owner all permissions anyway + * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) + * @param _delegate address of delegate + * @param _module address of PermissionManager module + * @param _perm the permissions + * @return success + */ + function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns(bool); +} diff --git a/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol index fdfd3df2e..0e2f71d93 100644 --- a/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol +++ b/contracts/libraries/BokkyPooBahsDateTimeLibrary.sol @@ -55,7 +55,7 @@ library BokkyPooBahsDateTimeLibrary { // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4 // - offset // ------------------------------------------------------------------------ - function _daysFromDate(uint year, uint month, uint day) internal pure returns(uint _days) { + function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) { require(year >= 1970); int _year = int(year); int _month = int(month); @@ -83,7 +83,7 @@ library BokkyPooBahsDateTimeLibrary { // month = month + 2 - 12 * L // year = 100 * (N - 49) + year + L // ------------------------------------------------------------------------ - function _daysToDate(uint _days) internal pure returns(uint year, uint month, uint day) { + function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) { int __days = int(_days); int L = __days + 68569 + OFFSET19700101; @@ -120,7 +120,7 @@ library BokkyPooBahsDateTimeLibrary { uint hour, uint minute, uint second - ) + ) { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); uint secs = timestamp % SECONDS_PER_DAY; @@ -130,7 +130,7 @@ library BokkyPooBahsDateTimeLibrary { second = secs % SECONDS_PER_MINUTE; } - function isValidDate(uint year, uint month, uint day) internal pure returns(bool valid) { + 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) { @@ -138,14 +138,14 @@ library BokkyPooBahsDateTimeLibrary { } } } - function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns(bool valid) { + 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) { + function isLeapYear(uint timestamp) internal pure returns (bool leapYear) { uint year; uint month; uint day; @@ -168,7 +168,7 @@ library BokkyPooBahsDateTimeLibrary { (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); daysInMonth = _getDaysInMonth(year, month); } - function _getDaysInMonth(uint year, uint month) internal pure returns(uint daysInMonth) { + 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) { @@ -178,22 +178,22 @@ library BokkyPooBahsDateTimeLibrary { } } // 1 = Monday, 7 = Sunday - function getDayOfWeek(uint timestamp) internal pure returns(uint dayOfWeek) { + 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) { + 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) { + 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) { + function getDay(uint timestamp) internal pure returns (uint day) { uint year; uint month; (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY); @@ -260,7 +260,7 @@ library BokkyPooBahsDateTimeLibrary { require(newTimestamp >= timestamp); } - function subYears(uint timestamp, uint _years) internal pure returns(uint newTimestamp) { + function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) { uint year; uint month; uint day; @@ -294,23 +294,20 @@ library BokkyPooBahsDateTimeLibrary { newTimestamp = timestamp - _days * SECONDS_PER_DAY; require(newTimestamp <= timestamp); } - - function subHours(uint timestamp, uint _hours) internal pure returns(uint newTimestamp) { + 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) { + 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) { + function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) { require(fromTimestamp <= toTimestamp); uint fromYear; uint fromMonth; @@ -350,7 +347,7 @@ library BokkyPooBahsDateTimeLibrary { 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; diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol new file mode 100644 index 000000000..3b3a05da2 --- /dev/null +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -0,0 +1,130 @@ +pragma solidity ^0.5.0; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../storage/VolumeRestrictionTMStorage.sol"; + +library VolumeRestrictionLib { + + using SafeMath for uint256; + + function _checkLengthOfArray( + address[] memory _holders, + uint256[] memory _allowedTokens, + uint256[] memory _startTimes, + uint256[] memory _rollingPeriodInDays, + uint256[] memory _endTimes, + uint256[] memory _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, 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(VolumeRestrictionTMStorage.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(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] = 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(VolumeRestrictionTMStorage.TypeOfPeriod.Both); + else + return _callFrom; + } + + function getRestrictionData( + VolumeRestrictionTMStorage.RestrictedData storage _holderData, + VolumeRestrictionTMStorage.IndividualRestrictions storage _individualRestrictions + ) public 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 < _holderData.restrictedAddresses.length; i++) { + counter = counter + (_holderData.restrictedHolders[_holderData.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 < _holderData.restrictedAddresses.length; i++) { + allAddresses[counter] = _holderData.restrictedAddresses[i]; + if (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8(VolumeRestrictionTMStorage.TypeOfPeriod.MultipleDays)) { + _setValues(_individualRestrictions.individualRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + } + else if (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8(VolumeRestrictionTMStorage.TypeOfPeriod.OneDay)) { + _setValues(_individualRestrictions.individualDailyRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + } + else if (_holderData.restrictedHolders[_holderData.restrictedAddresses[i]].typeOfPeriod == uint8(VolumeRestrictionTMStorage.TypeOfPeriod.Both)) { + _setValues(_individualRestrictions.individualRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + counter++; + allAddresses[counter] = _holderData.restrictedAddresses[i]; + _setValues(_individualRestrictions.individualDailyRestriction[_holderData.restrictedAddresses[i]], allowedTokens, startTime, rollingPeriodInDays, endTime, typeOfRestriction, counter); + } + counter++; + } + } + + function _setValues( + VolumeRestrictionTMStorage.VolumeRestriction memory restriction, + uint256[] memory allowedTokens, + uint256[] memory startTime, + uint256[] memory rollingPeriodInDays, + uint256[] memory endTime, + uint8[] memory typeOfRestriction, + uint256 index + ) + internal + pure + { + allowedTokens[index] = restriction.allowedTokens; + startTime[index] = restriction.startTime; + rollingPeriodInDays[index] = restriction.rollingPeriodInDays; + endTime[index] = restriction.endTime; + typeOfRestriction[index] = uint8(restriction.typeOfRestriction); + } + +} diff --git a/contracts/mocks/PolyTokenFaucet.sol b/contracts/mocks/PolyTokenFaucet.sol index c903223f6..4ebd9863f 100644 --- a/contracts/mocks/PolyTokenFaucet.sol +++ b/contracts/mocks/PolyTokenFaucet.sol @@ -17,8 +17,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; diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index e54aa27fa..92a89dc01 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -1,238 +1,400 @@ -/** - * 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.5.0; - -import "./ICheckpoint.sol"; -import "./DividendCheckpointStorage.sol"; -import "../Module.sol"; -import "../../interfaces/ISecurityToken.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/math/Math.sol"; - -/** - * @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[] memory) { - 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[] memory _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[] memory _investors, uint256[] memory _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[] memory _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 payable[] memory _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.min(investors.length, _start.add(_iterations)); - for (uint256 i = _start; i < numberInvestors; i++) { - address payable payee = address(uint160(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 payable _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[] memory) { - 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[] memory) { - bytes32[] memory allPermissions = new bytes32[](2); - allPermissions[0] = DISTRIBUTE; - allPermissions[1] = MANAGE; - return allPermissions; - } - -} +/** + * 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.5.0; + +import "./ICheckpoint.sol"; +import "./DividendCheckpointStorage.sol"; +import "../Module.sol"; +import "../../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/math/Math.sol"; + +/** + * @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); + event SetWallet(address indexed _oldWallet, address indexed _newWallet, 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 Function used to intialize the contract variables + * @param _wallet Ethereum account address to receive reclaimed dividends and tax + */ + function configure( + address payable _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 this.configure.selector; + } + + /** + * @notice Function used to change wallet address + * @param _wallet Ethereum account address to receive reclaimed dividends and tax + */ + function changeWallet(address payable _wallet) external onlyOwner { + _setWallet(_wallet); + } + + function _setWallet(address payable _wallet) internal { + require(_wallet != address(0)); + emit SetWallet(wallet, _wallet, now); + wallet = _wallet; + } + + /** + * @notice Return the default excluded addresses + * @return List of excluded addresses + */ + function getDefaultExcluded() external view returns(address[] memory) { + 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[] memory _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[] memory _investors, uint256[] memory _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[] memory _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 payable[] memory _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]; + uint256 checkpointId = dividend.checkpointId; + address[] memory investors = ISecurityToken(securityToken).getInvestorsAt(checkpointId); + uint256 numberInvestors = Math.min(investors.length, _start.add(_iterations)); + for (uint256 i = _start; i < numberInvestors; i++) { + address payable payee = address(uint160(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 payable _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[] memory) { + 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 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], maturitys[i], expirys[i], amounts[i], claimedAmounts[i], names[i]) = getDividendData(i); + } + } + + /** + * @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; + } + + /** + * @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 (estimate if not claimed) + * @return uint256[] amount of claim (estimate if not claimeed) + * @return uint256[] investor balance + */ + function getDividendProgress(uint256 _dividendIndex) external view returns ( + address[] memory investors, + bool[] memory resultClaimed, + bool[] memory resultExcluded, + uint256[] memory resultWithheld, + uint256[] memory resultAmount, + uint256[] memory resultBalance) + { + require(_dividendIndex < dividends.length, "Invalid dividend"); + //Get list of Investors + 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); + 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]) { + 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); + } + } + } + } + + /** + * @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]]; + } + } + + /** + * @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 + */ + function getPermissions() public view returns(bytes32[] memory) { + bytes32[] memory allPermissions = new bytes32[](2); + allPermissions[0] = DISTRIBUTE; + allPermissions[1] = MANAGE; + return allPermissions; + } + +} diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol index fa2f2793f..27315b16e 100644 --- a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol +++ b/contracts/modules/Checkpoint/DividendCheckpointStorage.sol @@ -5,7 +5,10 @@ pragma solidity ^0.5.0; * @dev abstract contract */ contract DividendCheckpointStorage { - uint256 public EXCLUDED_ADDRESS_LIMIT = 50; + + // Address to which reclaimed dividends and withholding tax is sent + address payable public wallet; + uint256 public EXCLUDED_ADDRESS_LIMIT = 150; bytes32 public constant DISTRIBUTE = "DISTRIBUTE"; bytes32 public constant MANAGE = "MANAGE"; bytes32 public constant CHECKPOINT = "CHECKPOINT"; @@ -14,16 +17,17 @@ contract DividendCheckpointStorage { 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) - 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 + bool reclaimed; // True if expiry has passed and issuer has reclaimed remaining dividend + 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 } @@ -34,7 +38,7 @@ contract DividendCheckpointStorage { address[] public excluded; // Mapping from address to withholding tax as a percentage * 10**16 - mapping(address => uint256) public withholdingTax; + 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 fecf21f8f..a672b88ef 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,279 +1,279 @@ -pragma solidity ^0.5.0; - -import "./DividendCheckpoint.sol"; -import "./ERC20DividendCheckpointStorage.sol"; -import "../../interfaces/IOwnable.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.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 - */ - constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { - - } - - /** - * @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[] memory _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[] memory _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[] memory _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 payable _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); - } - -} +pragma solidity ^0.5.0; + +import "./DividendCheckpoint.sol"; +import "./ERC20DividendCheckpointStorage.sol"; +import "../../interfaces/IOwnable.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.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 indexed _dividendIndex, address indexed _token, uint256 _amount, uint256 _withheld); + event ERC20DividendReclaimed(address indexed _claimer, uint256 indexed _dividendIndex, address indexed _token, uint256 _claimedAmount); + event ERC20DividendWithholdingWithdrawn( + address indexed _claimer, + uint256 indexed _dividendIndex, + address indexed _token, + uint256 _withheldAmount + ); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + */ + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + + } + + /** + * @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[] memory _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[] memory _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[] memory _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 payable _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"); + if (withheld > 0) { + _dividend.totalWithheld = _dividend.totalWithheld.add(withheld); + _dividend.withheld[_payee] = 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); + require(IERC20(dividendTokens[_dividendIndex]).transfer(wallet, remainingAmount), "transfer failed"); + emit ERC20DividendReclaimed(wallet, _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.totalWithheld.sub(dividend.totalWithheldWithdrawn); + dividend.totalWithheldWithdrawn = dividend.totalWithheld; + 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 b9b83ef0d..041c8222a 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,6 +1,8 @@ pragma solidity ^0.5.0; import "../../proxy/ERC20DividendCheckpointProxy.sol"; +import "../../libraries/Util.sol"; +import "../../interfaces/IBoot.sol"; import "../ModuleFactory.sol"; /** @@ -21,9 +23,9 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { uint256 _usageCost, uint256 _subscriptionCost, address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -39,14 +41,15 @@ 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 calldata /* _data */ - ) - external - returns(address) - { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); - address erc20DividendCheckpoint = address(new ERC20DividendCheckpointProxy(msg.sender, polyToken, logicContract)); + address erc20DividendCheckpoint = address(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*/ + bool success; + (success, ) = erc20DividendCheckpoint.call(_data); + require(success, "Unsuccessful 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 30ac0e724..0c8cae750 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpoint.sol @@ -1,218 +1,218 @@ -pragma solidity ^0.5.0; - -import "./DividendCheckpoint.sol"; -import "../../interfaces/IOwnable.sol"; - -/** - * @title Checkpoint module for issuing ether dividends - */ -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 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); - - /** - * @notice Constructor - * @param _securityToken Address of the security token - */ - constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { - - } - - /** - * @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 - */ - function createDividend(uint256 _maturity, uint256 _expiry, bytes32 _name) external payable withPerm(MANAGE) { - createDividendWithExclusions(_maturity, _expiry, excluded, _name); - } - - /** - * @notice Creates a dividend with a provided checkpoint, 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 _checkpointId Id of the checkpoint from which to issue dividend - * @param _name Name/title for identification - */ - function createDividendWithCheckpoint( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - bytes32 _name - ) - external - payable - withPerm(MANAGE) - { - _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, excluded, _name); - } - - /** - * @notice Creates a dividend and checkpoint for the dividend, specifying explicit 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 _excluded List of addresses to exclude - * @param _name Name/title for identification - */ - function createDividendWithExclusions( - uint256 _maturity, - uint256 _expiry, - address[] memory _excluded, - bytes32 _name - ) - public - payable - withPerm(MANAGE) - { - uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); - _createDividendWithCheckpointAndExclusions(_maturity, _expiry, checkpointId, _excluded, _name); - } - - /** - * @notice Creates a dividend with a provided checkpoint, specifying explicit 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 _checkpointId Id of the checkpoint from which to issue dividend - * @param _excluded List of addresses to exclude - * @param _name Name/title for identification - */ - function createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] memory _excluded, - bytes32 _name - ) - public - payable - withPerm(MANAGE) - { - _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, _excluded, _name); - } - - /** - * @notice Creates a dividend with a provided checkpoint, specifying explicit 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 _checkpointId Id of the checkpoint from which to issue dividend - * @param _excluded List of addresses to exclude - * @param _name Name/title for identification - */ - function _createDividendWithCheckpointAndExclusions( - uint256 _maturity, - uint256 _expiry, - uint256 _checkpointId, - address[] memory _excluded, - bytes32 _name - ) - internal - { - 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()); - require(_name[0] != 0); - uint256 dividendIndex = dividends.length; - uint256 currentSupply = ISecurityToken(securityToken).totalSupplyAt(_checkpointId); - uint256 excludedSupply = 0; - dividends.push( - Dividend( - _checkpointId, - now, /*solium-disable-line security/no-block-members*/ - _maturity, - _expiry, - msg.value, - 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(ISecurityToken(securityToken).balanceOfAt(_excluded[j], _checkpointId)); - 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); - } - - /** - * @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 payable _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { - (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); - _dividend.dividendWithheld = _dividend.dividendWithheld.add(withheld); - investorWithheld[_payee] = investorWithheld[_payee].add(withheld); - emit EtherDividendClaimed(_payee, _dividendIndex, claim, withheld); - } else { - _dividend.claimed[_payee] = false; - emit EtherDividendClaimFailed(_payee, _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, "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 is already claimed"); - Dividend storage dividend = dividends[_dividendIndex]; - dividend.reclaimed = true; - uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); - address payable owner = address(uint160(IOwnable(securityToken).owner())); - owner.transfer(remainingAmount); - emit EtherDividendReclaimed(owner, _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, "Incorrect dividend index"); - Dividend storage dividend = dividends[_dividendIndex]; - uint256 remainingWithheld = dividend.dividendWithheld.sub(dividend.dividendWithheldReclaimed); - dividend.dividendWithheldReclaimed = dividend.dividendWithheld; - address payable owner = address(uint160(IOwnable(securityToken).owner())); - owner.transfer(remainingWithheld); - emit EtherDividendWithholdingWithdrawn(owner, _dividendIndex, remainingWithheld); - } - -} +pragma solidity ^0.5.0; + +import "./DividendCheckpoint.sol"; +import "../../interfaces/IOwnable.sol"; + +/** + * @title Checkpoint module for issuing ether dividends + */ +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 indexed _dividendIndex, + bytes32 indexed _name + ); + 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 + * @param _securityToken Address of the security token + */ + constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + + } + + /** + * @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 + */ + function createDividend(uint256 _maturity, uint256 _expiry, bytes32 _name) external payable withPerm(MANAGE) { + createDividendWithExclusions(_maturity, _expiry, excluded, _name); + } + + /** + * @notice Creates a dividend with a provided checkpoint, 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 _checkpointId Id of the checkpoint from which to issue dividend + * @param _name Name/title for identification + */ + function createDividendWithCheckpoint( + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + bytes32 _name + ) + external + payable + withPerm(MANAGE) + { + _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, excluded, _name); + } + + /** + * @notice Creates a dividend and checkpoint for the dividend, specifying explicit 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 _excluded List of addresses to exclude + * @param _name Name/title for identification + */ + function createDividendWithExclusions( + uint256 _maturity, + uint256 _expiry, + address[] memory _excluded, + bytes32 _name + ) + public + payable + withPerm(MANAGE) + { + uint256 checkpointId = ISecurityToken(securityToken).createCheckpoint(); + _createDividendWithCheckpointAndExclusions(_maturity, _expiry, checkpointId, _excluded, _name); + } + + /** + * @notice Creates a dividend with a provided checkpoint, specifying explicit 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 _checkpointId Id of the checkpoint from which to issue dividend + * @param _excluded List of addresses to exclude + * @param _name Name/title for identification + */ + function createDividendWithCheckpointAndExclusions( + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] memory _excluded, + bytes32 _name + ) + public + payable + withPerm(MANAGE) + { + _createDividendWithCheckpointAndExclusions(_maturity, _expiry, _checkpointId, _excluded, _name); + } + + /** + * @notice Creates a dividend with a provided checkpoint, specifying explicit 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 _checkpointId Id of the checkpoint from which to issue dividend + * @param _excluded List of addresses to exclude + * @param _name Name/title for identification + */ + function _createDividendWithCheckpointAndExclusions( + uint256 _maturity, + uint256 _expiry, + uint256 _checkpointId, + address[] memory _excluded, + bytes32 _name + ) + internal + { + 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()); + require(_name[0] != 0); + uint256 dividendIndex = dividends.length; + uint256 currentSupply = ISecurityToken(securityToken).totalSupplyAt(_checkpointId); + uint256 excludedSupply = 0; + dividends.push( + Dividend( + _checkpointId, + now, /*solium-disable-line security/no-block-members*/ + _maturity, + _expiry, + msg.value, + 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(ISecurityToken(securityToken).balanceOfAt(_excluded[j], _checkpointId)); + 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); + } + + /** + * @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 payable _payee, Dividend storage _dividend, uint256 _dividendIndex) internal { + (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); + } + } + } + + /** + * @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, "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 is already claimed"); + Dividend storage dividend = dividends[_dividendIndex]; + dividend.reclaimed = true; + uint256 remainingAmount = dividend.amount.sub(dividend.claimedAmount); + wallet.transfer(remainingAmount); + emit EtherDividendReclaimed(wallet, _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, "Incorrect dividend index"); + Dividend storage dividend = dividends[_dividendIndex]; + uint256 remainingWithheld = dividend.totalWithheld.sub(dividend.totalWithheldWithdrawn); + dividend.totalWithheldWithdrawn = dividend.totalWithheld; + wallet.transfer(remainingWithheld); + emit EtherDividendWithholdingWithdrawn(wallet, _dividendIndex, remainingWithheld); + } + +} diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 92b1ba7f3..9802af2ee 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,6 +1,8 @@ pragma solidity ^0.5.0; import "../../proxy/EtherDividendCheckpointProxy.sol"; +import "../../libraries/Util.sol"; +import "../../interfaces/IBoot.sol"; import "../ModuleFactory.sol"; /** @@ -21,9 +23,9 @@ contract EtherDividendCheckpointFactory is ModuleFactory { uint256 _usageCost, uint256 _subscriptionCost, address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -39,14 +41,15 @@ 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 calldata /* _data */ - ) - external - returns(address) - { + function deploy(bytes calldata _data) external returns(address) { address polyToken = _takeFee(); - address ethDividendCheckpoint = address(new EtherDividendCheckpointProxy(msg.sender, polyToken, logicContract)); + address ethDividendCheckpoint = address(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*/ + bool success; + (success, ) = ethDividendCheckpoint.call(_data); + require(success, "Unsuccessful 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/Experimental/TransferManager/BlacklistTransferManager.sol b/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol new file mode 100644 index 000000000..68da9084b --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol @@ -0,0 +1,399 @@ +pragma solidity ^0.5.0; + +import "../../TransferManager/TransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module to automate blacklist and restrict transfers + */ +contract BlacklistTransferManager is TransferManager { + using SafeMath for uint256; + + bytes32 public constant ADMIN = "ADMIN"; + + struct BlacklistsDetails { + uint256 startTime; + uint256 endTime; + uint256 repeatPeriodTime; + } + + //hold the different blacklist details corresponds to its name + mapping(bytes32 => BlacklistsDetails) public blacklists; + + //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; + + //mapping use to store the indexes for different blacklist types for a investor + mapping(address => mapping(bytes32 => uint256)) investorToIndex; + + //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( + uint256 _startTime, + uint256 _endTime, + bytes32 _blacklistName, + uint256 _repeatPeriodTime + ); + + // Emit when there is a change in the blacklist type + event ModifyBlacklistType( + uint256 _startTime, + uint256 _endTime, + bytes32 _blacklistName, + uint256 _repeatPeriodTime + ); + + // Emit when the added blacklist type is deleted + event DeleteBlacklistType( + bytes32 _blacklistName + ); + + // Emit when new investor is added to the blacklist type + event AddInvestorToBlacklist( + address indexed _investor, + bytes32 _blacklistName + ); + + // Emit when investor is deleted from the blacklist type + event DeleteInvestorFromBlacklist( + address indexed _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 This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + + /** + * @notice Used to verify the transfer transaction + * @param _from Address of the sender + * @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 memory/* _data */, bool /* _isTransfer */) public returns(Result) { + if (!paused) { + if (investorToBlacklist[_from].length != 0) { + for (uint256 i = 0; i < investorToBlacklist[_from].length; i++) { + uint256 endTimeTemp = blacklists[investorToBlacklist[_from][i]].endTime; + uint256 startTimeTemp = blacklists[investorToBlacklist[_from][i]].startTime; + uint256 repeatPeriodTimeTemp = blacklists[investorToBlacklist[_from][i]].repeatPeriodTime * 1 days; + /*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(repeatPeriodTimeTemp); + /*solium-disable-next-line security/no-block-members*/ + if (startTimeTemp.add(repeatPeriodTimeTemp.mul(repeater)) <= now && endTimeTemp.add(repeatPeriodTimeTemp.mul(repeater)) >= now) { + return Result.INVALID; + } + } + } + } + } + return Result.NA; + } + + /** + * @notice Used to add the blacklist type + * @param _startTime Start date of the blacklist type + * @param _endTime End date 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 _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 _blacklistNames Name of the blacklist type + * @param _repeatPeriodTimes Repeat period of the blacklist type + */ + function addBlacklistTypeMulti( + uint256[] calldata _startTimes, + uint256[] calldata _endTimes, + bytes32[] calldata _blacklistNames, + uint256[] calldata _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], _blacklistNames[i], _repeatPeriodTimes[i]); + } + } + + /** + * @notice Internal function + */ + 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); + } + + /** + * @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 _blacklistName Name of the blacklist type + * @param _repeatPeriodTime Repeat period of the blacklist type + */ + 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, _repeatPeriodTime); + 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 _blacklistNames Name of the blacklist type + * @param _repeatPeriodTimes Repeat period of the blacklist type + */ + function modifyBlacklistTypeMulti( + uint256[] calldata _startTimes, + uint256[] calldata _endTimes, + bytes32[] calldata _blacklistNames, + uint256[] calldata _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], _blacklistNames[i], _repeatPeriodTimes[i]); + } + } + + /** + * @notice Used to delete the blacklist type + * @param _blacklistName Name of the blacklist type + */ + 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[_blacklistName]); + uint256 i = 0; + for (i = 0; i < allBlacklists.length; i++) { + if (allBlacklists[i] == _blacklistName) { + break; + } + } + if (i != allBlacklists.length -1) { + allBlacklists[i] = allBlacklists[allBlacklists.length -1]; + } + allBlacklists.length--; + emit DeleteBlacklistType(_blacklistName); + } + + /** + * @notice Used to delete the multiple blacklist type + * @param _blacklistNames Name of the blacklist type + */ + function deleteBlacklistTypeMulti(bytes32[] calldata _blacklistNames) external withPerm(ADMIN) { + for(uint256 i = 0; i < _blacklistNames.length; i++){ + deleteBlacklistType(_blacklistNames[i]); + } + } + + /** + * @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(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; + uint256 blacklistIndex = blacklistToInvestor[_blacklistName].length; + // 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 assign the blacklist type to the multiple investor + * @param _investors Address of the investor + * @param _blacklistName Name of the blacklist + */ + function addInvestorToBlacklistMulti(address[] calldata _investors, bytes32 _blacklistName) external withPerm(ADMIN){ + for(uint256 i = 0; i < _investors.length; i++){ + addInvestorToBlacklist(_investors[i], _blacklistName); + } + } + + /** + * @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[] calldata _investors, bytes32[] calldata _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]); + } + } + + /** + * @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 _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 _blacklistName, uint256 _repeatPeriodTime, address _investor) external withPerm(ADMIN){ + _addBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); + addInvestorToBlacklist(_investor, _blacklistName); + } + + /** + * @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"); + require(investorToBlacklist[_investor].length != 0, "Investor is not associated to any blacklist type"); + uint256 index = investorToBlacklist[_investor].length - 1; + for (uint256 i = index; i >= 0 && i <= index; i--){ + deleteInvestorFromBlacklist(_investor, investorToBlacklist[_investor][i]); + } + } + + /** + * @notice Used to delete the multiple investor from all the associated blacklist types + * @param _investor Address of the investor + */ + function deleteInvestorFromAllBlacklistMulti(address[] calldata _investor) external 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 + * @param _blacklistName Name of the blacklist + */ + 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]] == _blacklistName, "Investor not associated to the blacklist"); + // delete the investor from the blacklist type + uint256 _blacklistIndex = blacklistToIndex[_blacklistName][_investor]; + uint256 _len = blacklistToInvestor[_blacklistName].length; + if ( _blacklistIndex < _len -1) { + blacklistToInvestor[_blacklistName][_blacklistIndex] = blacklistToInvestor[_blacklistName][_len - 1]; + blacklistToIndex[_blacklistName][blacklistToInvestor[_blacklistName][_blacklistIndex]] = _blacklistIndex; + } + blacklistToInvestor[_blacklistName].length--; + // delete the investor index from the blacklist + delete(blacklistToIndex[_blacklistName][_investor]); + // delete the blacklist from the investor + uint256 _investorIndex = investorToIndex[_investor][_blacklistName]; + _len = investorToBlacklist[_investor].length; + if ( _investorIndex < _len -1) { + investorToBlacklist[_investor][_investorIndex] = investorToBlacklist[_investor][_len - 1]; + investorToIndex[_investor][investorToBlacklist[_investor][_investorIndex]] = _investorIndex; + } + investorToBlacklist[_investor].length--; + // delete the blacklist index from the invetsor + delete(investorToIndex[_investor][_blacklistName]); + emit DeleteInvestorFromBlacklist(_investor, _blacklistName); + } + + /** + * @notice Used to delete the multiple investor from the blacklist + * @param _investors address of the investor + * @param _blacklistNames name of the blacklist + */ + function deleteMultiInvestorsFromBlacklistMulti(address[] calldata _investors, bytes32[] calldata _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]); + } + } + + function _addBlacklistType(uint256 _startTime, uint256 _endTime, bytes32 _blacklistName, uint256 _repeatPeriodTime) internal { + require(blacklists[_blacklistName].endTime == 0, "Blacklist type already exist"); + _validParams(_startTime, _endTime, _blacklistName, _repeatPeriodTime); + blacklists[_blacklistName] = BlacklistsDetails(_startTime, _endTime, _repeatPeriodTime); + allBlacklists.push(_blacklistName); + emit AddBlacklistType(_startTime, _endTime, _blacklistName, _repeatPeriodTime); + } + + /** + * @notice get the list of the investors of a blacklist type + * @param _blacklistName Name of the blacklist type + * @return address List of investors associated with the blacklist + */ + function getListOfAddresses(bytes32 _blacklistName) external view returns(address[] memory) { + 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[] memory) { + return investorToBlacklist[_user]; + } + + /** + * @notice get the list of blacklist names + * @return bytes32 Array of blacklist names + */ + function getAllBlacklists() external view returns(bytes32[] memory) { + return allBlacklists; + } + + /** + * @notice Return the permissions flag that are associated with blacklist transfer manager + */ + function getPermissions() public view returns(bytes32[] memory) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } +} diff --git a/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol new file mode 100644 index 000000000..d193864b9 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol @@ -0,0 +1,68 @@ +pragma solidity ^0.5.0; + +import "./BlacklistTransferManager.sol"; +import "../../ModuleFactory.sol"; +import "../../../libraries/Util.sol"; + +/** + * @title Factory for deploying BlacklistManager module + */ +contract BlacklistTransferManagerFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + { + version = "2.1.0"; + 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)); + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes calldata /* _data */) external returns(address) { + address polyToken = _takeFee(); + address blacklistTransferManager = address(new BlacklistTransferManager(msg.sender, address(polyToken))); + /*solium-disable-next-line security/no-block-members*/ + emit GenerateModuleFromFactory(blacklistTransferManager, getName(), address(this), msg.sender, setupCost, now); + return blacklistTransferManager; + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[] memory) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; + } + + /** + * @notice Get the Instructions that helped to used the module + */ + function getInstructions() public view returns(string memory) { + return "Allows an issuer to blacklist the addresses."; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[] memory) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "Blacklist"; + availableTags[1] = "Restricted transfer"; + return availableTags; + } + + +} diff --git a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol new file mode 100644 index 000000000..bcb60b149 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol @@ -0,0 +1,636 @@ +pragma solidity ^0.5.0; + +import "../../TransferManager/TransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +contract LockUpTransferManager is TransferManager { + + 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 memory /* _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[] calldata _lockupAmounts, + uint256[] calldata _startTimes, + uint256[] calldata _lockUpPeriodsSeconds, + uint256[] calldata _releaseFrequenciesSeconds, + bytes32[] calldata _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[] calldata _userAddresses, + bytes32[] calldata _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[] memory _userAddresses, + uint256[] memory _lockupAmounts, + uint256[] memory _startTimes, + uint256[] memory _lockUpPeriodsSeconds, + uint256[] memory _releaseFrequenciesSeconds, + bytes32[] memory _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[] calldata _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[] calldata _userAddresses, bytes32[] calldata _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[] memory _lockupAmounts, + uint256[] memory _startTimes, + uint256[] memory _lockUpPeriodsSeconds, + uint256[] memory _releaseFrequenciesSeconds, + bytes32[] memory _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[] memory) { + 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[] memory) { + 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[] memory) { + 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 = IERC20(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[] memory) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } +} diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol similarity index 71% rename from contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol rename to contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol index a677cccdf..846133da6 100644 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTMFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol @@ -1,12 +1,13 @@ pragma solidity ^0.5.0; -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 * @param _setupCost Setup cost of the module @@ -17,13 +18,13 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ) + public + ModuleFactory(_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)); @@ -35,15 +36,15 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { */ function deploy( bytes calldata /* _data */ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); - LockupVolumeRestrictionTM lockupVolumeRestrictionTransferManager = new LockupVolumeRestrictionTM(msg.sender, polyToken); + LockUpTransferManager lockUpTransferManager = new LockUpTransferManager(msg.sender, 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, setupCost, now); + return address(lockUpTransferManager); } /** @@ -68,7 +69,7 @@ contract LockupVolumeRestrictionTMFactory is ModuleFactory { */ function getTags() external view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); - availableTags[0] = "Volume"; + availableTags[0] = "LockUp"; availableTags[1] = "Transfer Restriction"; return availableTags; } diff --git a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol deleted file mode 100644 index 5d0ac2307..000000000 --- a/contracts/modules/Experimental/TransferManager/LockupVolumeRestrictionTM.sol +++ /dev/null @@ -1,403 +0,0 @@ -pragma solidity ^0.5.0; - -import "./../../TransferManager/TransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -contract LockupVolumeRestrictionTM is TransferManager { - 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 - */ - constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { - - } - - /** @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 calldata, /* _data */ - bool _isTransfer - ) - external - 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[] calldata _userAddresses, - uint[] calldata _lockUpPeriodsSeconds, - uint[] calldata _releaseFrequenciesSeconds, - uint[] calldata _startTimes, - uint[] calldata _totalAmounts - ) - external - withPerm(ADMIN) - { - require( - _userAddresses.length == _lockUpPeriodsSeconds.length && _userAddresses.length == _releaseFrequenciesSeconds.length && _userAddresses.length == _startTimes.length && _userAddresses.length == _totalAmounts.length, /*solium-disable-line operator-whitespace*/ /*solium-disable-line operator-whitespace*/ - "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), uint256(0), uint256(0)]; // allowed amount right now // total locked up, ever // 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 (uint256 i = 0; i < userLockUps.length; i++) { - LockUp storage 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[] memory) { - bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = ADMIN; - return allPermissions; - } -} diff --git a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol b/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol deleted file mode 100644 index 431408336..000000000 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTM.sol +++ /dev/null @@ -1,338 +0,0 @@ -pragma solidity ^0.5.0; - -import "./../../TransferManager/TransferManager.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/** - * @title Transfer Manager for limiting volume of tokens in a single trade - */ - -contract SingleTradeVolumeRestrictionTM is TransferManager { - using SafeMath for uint256; - - bytes32 public constant 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 - */ - constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { - - } - - /** @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 calldata /* _data */, - bool /* _isTransfer */ - ) - external - 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[] memory _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[] memory _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[] memory _wallets, uint[] memory _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[] memory _wallets, - uint[] memory _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[] memory _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[] memory _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[] memory) { - 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 d00a32bf0..000000000 --- a/contracts/modules/Experimental/TransferManager/SingleTradeVolumeRestrictionTMFactory.sol +++ /dev/null @@ -1,81 +0,0 @@ -pragma solidity ^0.5.0; - -import "./../../ModuleFactory.sol"; -import "./SingleTradeVolumeRestrictionTM.sol"; -import "../../../libraries/Util.sol"; - -/** - * @title Factory for deploying SingleTradeVolumeRestrictionManager - */ -contract SingleTradeVolumeRestrictionTMFactory is ModuleFactory { - /** - * @notice Constructor - * @param _setupCost Setup cost of the module - * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module - */ - constructor( - uint256 _setupCost, - uint256 _usageCost, - uint256 _subscriptionCost - ) - public - ModuleFactory(_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 calldata _data) external returns(address) { - address polyToken = _takeFee(); - SingleTradeVolumeRestrictionTM singleTradeVolumeRestrictionManager = new SingleTradeVolumeRestrictionTM(msg.sender, polyToken); - require(Util.getSig(_data) == singleTradeVolumeRestrictionManager.getInitFunction(), "Provided data is not valid"); - bool success; - /*solium-disable-next-line security/no-low-level-calls*/ - (success, ) = address(singleTradeVolumeRestrictionManager).call(_data); - require(success, "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[] memory) { - 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 memory) { - /*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[] memory) { - bytes32[] memory availableTags = new bytes32[](3); - availableTags[0] = "Single Trade"; - availableTags[1] = "Transfer"; - availableTags[2] = "Volume"; - return availableTags; - } - -} diff --git a/contracts/modules/Experimental/Wallet/IWallet.sol b/contracts/modules/Experimental/Wallet/IWallet.sol new file mode 100644 index 000000000..013bcc540 --- /dev/null +++ b/contracts/modules/Experimental/Wallet/IWallet.sol @@ -0,0 +1,19 @@ +pragma solidity ^0.5.0; + +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/modules/Experimental/Wallet/VestingEscrowWallet.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol new file mode 100644 index 000000000..5b483cdf5 --- /dev/null +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol @@ -0,0 +1,566 @@ +pragma solidity ^0.5.0; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../../../storage/VestingEscrowWalletStorage.sol"; +import "./IWallet.sol"; +import "../../../interfaces/ISecurityToken.sol"; + +/** + * @title Wallet for core vesting escrow functionality + */ +contract VestingEscrowWallet is VestingEscrowWalletStorage, IWallet { + using SafeMath for uint256; + + bytes32 public constant ADMIN = "ADMIN"; + + // States used to represent the status of the schedule + enum State {CREATED, STARTED, COMPLETED} + + // Emit when new schedule is added + event AddSchedule( + address indexed _beneficiary, + bytes32 _templateName, + uint256 _startTime + ); + // Emit when schedule is modified + event ModifySchedule( + address indexed _beneficiary, + bytes32 _templateName, + uint256 _startTime + ); + // Emit when all schedules are revoked for user + event RevokeAllSchedules(address indexed _beneficiary); + // 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); + // Emit when template is added + 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 + * @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 the configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(keccak256("configure(address)")); + } + + /** + * @notice Used to initialize 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 Used 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; + } + + /** + * @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); + } + + function _depositTokens(uint256 _numberOfTokens) internal { + require(_numberOfTokens > 0, "Should be > 0"); + 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 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"); + require(_amount <= unassignedTokens, "Amount is greater than unassigned tokens"); + uint256 amount = unassignedTokens; + unassignedTokens = 0; + require(ISecurityToken(securityToken).transfer(treasuryWallet, amount), "Transfer failed"); + emit SendToTreasury(amount, msg.sender); + } + + /** + * @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); + } + + /** + * @notice Used to withdraw available tokens by beneficiary + */ + function pullAvailableTokens() external { + _sendTokens(msg.sender); + } + + /** + * @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); + } + + function _addTemplate(bytes32 _name, uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal { + require(_name != bytes32(0), "Invalid name"); + require(!_isTemplateExists(_name), "Already exists"); + _validateTemplate(_numberOfTokens, _duration, _frequency); + templateNames.push(_name); + templates[_name] = Template(_numberOfTokens, _duration, _frequency, templateNames.length - 1); + emit AddTemplate(_name, _numberOfTokens, _duration, _frequency); + } + + /** + * @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"); + require(templateToUsers[_name].length == 0, "Template is used"); + uint256 index = templates[_name].index; + if (index != templateNames.length - 1) { + templateNames[index] = templateNames[templateNames.length - 1]; + templates[templateNames[index]].index = index; + } + templateNames.length--; + // delete template data + delete templates[_name]; + emit RemoveTemplate(_name); + } + + /** + * @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 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[] memory) { + return templateNames; + } + + /** + * @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, + bytes32 _templateName, + uint256 _numberOfTokens, + uint256 _duration, + uint256 _frequency, + uint256 _startTime + ) + external + withPerm(ADMIN) + { + _addSchedule(_beneficiary, _templateName, _numberOfTokens, _duration, _frequency, _startTime); + } + + function _addSchedule( + address _beneficiary, + bytes32 _templateName, + uint256 _numberOfTokens, + uint256 _duration, + uint256 _frequency, + uint256 _startTime + ) + internal + { + _addTemplate(_templateName, _numberOfTokens, _duration, _frequency); + _addScheduleFromTemplate(_beneficiary, _templateName, _startTime); + } + + /** + * @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); + } + + function _addScheduleFromTemplate(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { + require(_beneficiary != address(0), "Invalid address"); + require(_isTemplateExists(_templateName), "Template not found"); + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; + require( + schedules[_beneficiary].length == 0 || + schedules[_beneficiary][index].templateName != _templateName, + "Already added" + ); + require(_startTime >= now, "Date in the past"); + uint256 numberOfTokens = templates[_templateName].numberOfTokens; + if (numberOfTokens > unassignedTokens) { + _depositTokens(numberOfTokens.sub(unassignedTokens)); + } + unassignedTokens = unassignedTokens.sub(numberOfTokens); + if (!beneficiaryAdded[_beneficiary]) { + beneficiaries.push(_beneficiary); + beneficiaryAdded[_beneficiary] = true; + } + schedules[_beneficiary].push(Schedule(_templateName, 0, _startTime)); + userToTemplates[_beneficiary].push(_templateName); + userToTemplateIndex[_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 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); + } + + function _modifySchedule(address _beneficiary, bytes32 _templateName, uint256 _startTime) internal { + _checkSchedule(_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"); + schedule.startTime = _startTime; + emit ModifySchedule(_beneficiary, _templateName, _startTime); + } + + /** + * @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); + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; + _sendTokensPerSchedule(_beneficiary, index); + uint256 releasedTokens = _getReleasedTokens(_beneficiary, index); + unassignedTokens = unassignedTokens.add(templates[_templateName].numberOfTokens.sub(releasedTokens)); + _deleteUserToTemplates(_beneficiary, _templateName); + _deleteTemplateToUsers(_beneficiary, _templateName); + emit RevokeSchedule(_beneficiary, _templateName); + } + + function _deleteUserToTemplates(address _beneficiary, bytes32 _templateName) internal { + 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 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]; + } + + /** + * @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); + } + + function _revokeAllSchedules(address _beneficiary) internal { + require(_beneficiary != address(0), "Invalid address"); + _sendTokens(_beneficiary); + Schedule[] storage userSchedules = schedules[_beneficiary]; + for (uint256 i = 0; i < userSchedules.length; i++) { + uint256 releasedTokens = _getReleasedTokens(_beneficiary, i); + Template memory template = templates[userSchedules[i].templateName]; + unassignedTokens = unassignedTokens.add(template.numberOfTokens.sub(releasedTokens)); + delete userToTemplateIndex[_beneficiary][userSchedules[i].templateName]; + _deleteTemplateToUsers(_beneficiary, userSchedules[i].templateName); + } + delete schedules[_beneficiary]; + delete userToTemplates[_beneficiary]; + emit RevokeAllSchedules(_beneficiary); + } + + /** + * @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) { + _checkSchedule(_beneficiary, _templateName); + 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 = userToTemplateIndex[_beneficiary][_templateName]; + Schedule memory schedule = schedules[_beneficiary][index]; + if (now < schedule.startTime) { + return State.CREATED; + } else if (now > schedule.startTime && now < schedule.startTime.add(templates[_templateName].duration)) { + return State.STARTED; + } else { + return State.COMPLETED; + } + } + + /** + * @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[] memory) { + require(_beneficiary != address(0), "Invalid address"); + return userToTemplates[_beneficiary]; + } + + /** + * @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"); + return schedules[_beneficiary].length; + } + + function _getAvailableTokens(address _beneficiary, uint256 _index) internal view returns(uint256) { + 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 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); + /*solium-disable-next-line security/no-block-members*/ + uint256 periodNumber = (now.sub(schedule.startTime)).div(template.frequency); + if (periodNumber > periodCount) { + periodNumber = periodCount; + } + return template.numberOfTokens.mul(periodNumber).div(periodCount); + } else { + return 0; + } + } + + /** + * @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"); + for (uint256 i = _fromIndex; i <= _toIndex; i++) { + if (schedules[beneficiaries[i]].length !=0) + pushAvailableTokens(beneficiaries[i]); + } + } + + /** + * @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[] memory _beneficiaries, + bytes32[] memory _templateNames, + uint256[] memory _numberOfTokens, + uint256[] memory _durations, + uint256[] memory _frequencies, + uint256[] memory _startTimes + ) + 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*/ + _beneficiaries.length == _startTimes.length, + "Arrays sizes mismatch" + ); + for (uint256 i = 0; i < _beneficiaries.length; 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 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[] calldata _beneficiaries, + bytes32[] calldata _templateNames, + uint256[] calldata _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], _templateNames[i], _startTimes[i]); + } + } + + /** + * @notice Used to bulk revoke vesting schedules for each of the beneficiaries + * @param _beneficiaries Array of the beneficiary's addresses + */ + function revokeSchedulesMulti(address[] calldata _beneficiaries) external withPerm(ADMIN) { + for (uint256 i = 0; i < _beneficiaries.length; i++) { + _revokeAllSchedules(_beneficiaries[i]); + } + } + + /** + * @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[] memory _beneficiaries, + bytes32[] memory _templateNames, + uint256[] memory _startTimes + ) + public + withPerm(ADMIN) + { + require( + _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], _templateNames[i], _startTimes[i]); + } + } + + function _checkSchedule(address _beneficiary, bytes32 _templateName) internal view { + require(_beneficiary != address(0), "Invalid address"); + uint256 index = userToTemplateIndex[_beneficiary][_templateName]; + require( + index < schedules[_beneficiary].length && + schedules[_beneficiary][index].templateName == _templateName, + "Schedule not found" + ); + } + + function _isTemplateExists(bytes32 _name) internal view returns(bool) { + return templates[_name].numberOfTokens > 0; + } + + function _validateTemplate(uint256 _numberOfTokens, uint256 _duration, uint256 _frequency) internal view { + require(_numberOfTokens > 0, "Zero amount"); + require(_duration % _frequency == 0, "Invalid frequency"); + uint256 periodCount = _duration.div(_frequency); + 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++) { + _sendTokensPerSchedule(_beneficiary, i); + } + } + + 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); + require(ISecurityToken(securityToken).transfer(_beneficiary, amount), "Transfer failed"); + emit SendTokens(_beneficiary, amount); + } + } + + /** + * @notice Return the permissions flag that are associated with VestingEscrowWallet + */ + function getPermissions() public view returns(bytes32[] memory) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } + +} diff --git a/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol new file mode 100644 index 000000000..0ddf7123d --- /dev/null +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol @@ -0,0 +1,75 @@ +pragma solidity ^0.5.0; + +import "../../../proxy/VestingEscrowWalletProxy.sol"; +import "../../../interfaces/IBoot.sol"; +import "../../ModuleFactory.sol"; +import "../../../libraries/Util.sol"; + +/** + * @title Factory for deploying VestingEscrowWallet module + */ +contract VestingEscrowWalletFactory is ModuleFactory { + + address public logicContract; + /** + * @notice Constructor + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + ModuleFactory(_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; + } + + /** + * @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 calldata _data) external returns(address) { + address polyToken = _takeFee(); + address vestingEscrowWallet = address(new VestingEscrowWalletProxy(msg.sender, address(polyToken), logicContract)); + //Checks that _data is valid (not calling anything it shouldn't) + require(Util.getSig(_data) == IBoot(vestingEscrowWallet).getInitFunction(), "Invalid data"); + bool success; + /*solium-disable-next-line security/no-low-level-calls*/ + (success, ) = vestingEscrowWallet.call(_data); + require(success, "Unsuccessfull call"); + /*solium-disable-next-line security/no-block-members*/ + emit GenerateModuleFromFactory(vestingEscrowWallet, getName(), address(this), msg.sender, setupCost, now); + return vestingEscrowWallet; + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[] memory) { + 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 memory) { + /*solium-disable-next-line max-len*/ + 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."; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[] memory) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "Vested"; + availableTags[1] = "Escrow Wallet"; + return availableTags; + } +} diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index e2db5f6d9..f6c967f77 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -1,8 +1,7 @@ pragma solidity ^0.5.0; -import "../RegistryUpdater.sol"; import "../interfaces/IModule.sol"; -import "../interfaces/ISecurityToken.sol"; +import "../interfaces/ICheckPermission.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./ModuleStorage.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; @@ -16,8 +15,9 @@ contract Module is IModule, ModuleStorage { * @notice Constructor * @param _securityToken Address of the security token */ - constructor(address _securityToken, address _polyToken) public ModuleStorage(_securityToken, _polyToken) { - + constructor (address _securityToken, address _polyAddress) public + ModuleStorage(_securityToken, _polyAddress) + { } //Allows owner, factory or permissioned delegate @@ -25,7 +25,7 @@ contract Module is IModule, ModuleStorage { bool isOwner = msg.sender == Ownable(securityToken).owner(); bool isFactory = msg.sender == factory; require( - isOwner || isFactory || ISecurityToken(securityToken).checkPermission(msg.sender, address(this), _perm), + isOwner || isFactory || ICheckPermission(securityToken).checkPermission(msg.sender, address(this), _perm), "Permission check failed" ); _; diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index 9cf1ffcc4..28abaa38a 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -27,18 +27,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 */ diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 4587785f0..6469ac3bb 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -3,6 +3,7 @@ pragma solidity ^0.5.0; import "./IPermissionManager.sol"; import "../Module.sol"; import "./GeneralPermissionManagerStorage.sol"; +import "../../interfaces/ISecurityToken.sol"; /** * @title Permission Manager module for core permissioning functionality @@ -109,9 +110,9 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio address[] calldata _modules, bytes32[] calldata _perms, bool[] calldata _valids - ) - external - withPerm(CHANGE_PERMISSION) + ) + external + withPerm(CHANGE_PERMISSION) { require(_delegate != address(0), "invalid address"); require(_modules.length > 0, "0 length is not allowed"); diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 3c7adcd0b..596936e37 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -51,9 +51,9 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { uint256 _rate, FundRaiseType[] memory _fundRaiseTypes, address payable _fundsReceiver - ) - public - onlyFactory + ) + public + onlyFactory { require(endTime == 0, "Already configured"); require(_rate > 0, "Rate of token should be greater than 0"); diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 06090758c..abb32f9d5 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -29,7 +29,7 @@ contract CappedSTOFactory is ModuleFactory { ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); - 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/contracts/modules/STO/ISTOStorage.sol b/contracts/modules/STO/ISTOStorage.sol new file mode 100644 index 000000000..4ff7b9294 --- /dev/null +++ b/contracts/modules/STO/ISTOStorage.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.5.0; + +/** + * @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/STO.sol b/contracts/modules/STO/STO.sol index 088e84951..d3f28c5fd 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -13,7 +13,7 @@ import "../../interfaces/ISTO.sol"; contract STO is ISTO, STOStorage, Module, Pausable { using SafeMath for uint256; - enum FundRaiseType {ETH, POLY, DAI} + enum FundRaiseType {ETH, POLY, SC} // Event event SetFundRaiseTypes(FundRaiseType[] _fundRaiseTypes); @@ -37,6 +37,11 @@ contract STO is ISTO, STOStorage, Module, Pausable { return fundsRaised[uint8(_fundRaiseType)]; } + /** + * @notice Returns the total no. of tokens sold + */ + function getTokensSold() external view returns (uint256); + /** * @notice Pause (overridden function) */ @@ -58,7 +63,7 @@ contract STO is ISTO, STOStorage, 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 cea3a45f5..20cce3e87 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -6,17 +6,16 @@ import "../../interfaces/IOracle.sol"; import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; -import "./USDTieredSTOStorage.sol"; +import "../../storage/USDTieredSTOStorage.sol"; /** * @title STO module for standard capped crowdsale */ -contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { +contract USDTieredSTO is USDTieredSTOStorage, STO { using SafeMath for uint256; - string public constant POLY_ORACLE = "PolyUsdOracle"; - string public constant ETH_ORACLE = "EthUsdOracle"; + string internal constant POLY_ORACLE = "PolyUsdOracle"; + string internal constant ETH_ORACLE = "EthUsdOracle"; //////////// // Events // @@ -43,7 +42,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256 _rate ); event ReserveTokenMint(address indexed _owner, address indexed _wallet, uint256 _tokens, uint256 _latestTier); - event SetAddresses(address indexed _wallet, address indexed _reserveWallet, address indexed _usdToken); + event SetAddresses(address indexed _wallet, address indexed _reserveWallet, address[] _usdTokens); event SetLimits(uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD); event SetTimes(uint256 _startTime, uint256 _endTime); event SetTiers( @@ -69,8 +68,8 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { _; } - modifier validDAI() { - require(fundRaiseTypes[uint8(FundRaiseType.DAI)], "DAI not allowed"); + modifier validSC(address _usdToken) { + require(fundRaiseTypes[uint8(FundRaiseType.SC)] && usdTokenEnabled[_usdToken], "USD not allowed"); _; } @@ -93,7 +92,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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 Contract address of the stable coins */ function configure( uint256 _startTime, @@ -107,10 +106,10 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { FundRaiseType[] memory _fundRaiseTypes, address payable _wallet, address _reserveWallet, - address _usdToken - ) - public - onlyFactory + address[] memory _usdTokens + ) + public + onlyFactory { oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; @@ -119,7 +118,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { _modifyTiers(_ratePerTier, _ratePerTierDiscountPoly, _tokensPerTierTotal, _tokensPerTierDiscountPoly); // NB - _setFundRaiseType must come before modifyAddresses _setFundRaiseType(_fundRaiseTypes); - _modifyAddresses(_wallet, _reserveWallet, _usdToken); + _modifyAddresses(_wallet, _reserveWallet, _usdTokens); _modifyLimits(_nonAccreditedLimitUSD, _minimumInvestmentUSD); } @@ -156,9 +155,9 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256[] calldata _ratePerTierDiscountPoly, uint256[] calldata _tokensPerTierTotal, uint256[] calldata _tokensPerTierDiscountPoly - ) - external - onlyOwner + ) + external + onlyOwner { /*solium-disable-next-line security/no-block-members*/ require(now < startTime, "STO already started"); @@ -180,12 +179,10 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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 payable _wallet, address _reserveWallet, address _usdToken) external onlyOwner { - /*solium-disable-next-line security/no-block-members*/ - require(now < startTime, "STO already started"); - _modifyAddresses(_wallet, _reserveWallet, _usdToken); + function modifyAddresses(address payable _wallet, address _reserveWallet, address[] calldata _usdTokens) external onlyOwner { + _modifyAddresses(_wallet, _reserveWallet, _usdTokens); } function _modifyLimits(uint256 _nonAccreditedLimitUSD, uint256 _minimumInvestmentUSD) internal { @@ -199,13 +196,15 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { uint256[] memory _ratePerTierDiscountPoly, uint256[] memory _tokensPerTierTotal, uint256[] memory _tokensPerTierDiscountPoly - ) - internal + ) + 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" + _tokensPerTierTotal.length > 0 && + _ratePerTier.length == _tokensPerTierTotal.length && + _ratePerTierDiscountPoly.length == _tokensPerTierTotal.length && + _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, + "Invalid Input" ); delete tiers; for (uint256 i = 0; i < _ratePerTier.length; i++) { @@ -226,15 +225,24 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { emit SetTimes(_startTime, _endTime); } - function _modifyAddresses(address payable _wallet, address _reserveWallet, address _usdToken) internal { + function _modifyAddresses(address payable _wallet, address _reserveWallet, address[] memory _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); + _modifyUSDTokens(_usdTokens); + } + + function _modifyUSDTokens(address[] memory _usdTokens) internal { + uint256 i; + for(i = 0; i < usdTokens.length; i++) { + usdTokenEnabled[usdTokens[i]] = false; + } + 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); } //////////////////// @@ -246,7 +254,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice Reserve address must be whitelisted to successfully finalize */ function finalize() public onlyOwner { - require(!isFinalized, "STO is already finalized"); + require(!isFinalized, "STO already finalized"); isFinalized = true; uint256 tempReturned; uint256 tempSold; @@ -259,7 +267,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { tiers[i].mintedTotal = tiers[i].tokenTotal; } } - require(ISecurityToken(securityToken).mint(reserveWallet, tempReturned), "Error in minting"); + require(ISecurityToken(securityToken).mint(reserveWallet, tempReturned), "Minting Failed"); emit ReserveTokenMint(msg.sender, reserveWallet, tempReturned, currentTier); finalAmountReturned = tempReturned; totalTokensSold = tempSold; @@ -273,7 +281,12 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { function changeAccredited(address[] memory _investors, bool[] memory _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]); } } @@ -287,12 +300,36 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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[] memory, bool[] memory, uint256[] memory) { + 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 @@ -315,16 +352,16 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { } // Buy functions without rate restriction - function buyWithETH(address _beneficiary) external payable { - buyWithETHRateLimited(_beneficiary, 0); + function buyWithETH(address _beneficiary) external payable returns (uint256, uint256, uint256) { + return buyWithETHRateLimited(_beneficiary, 0); } - function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) external { - buyWithPOLYRateLimited(_beneficiary, _investedPOLY, 0); + function buyWithPOLY(address _beneficiary, uint256 _investedPOLY) external returns (uint256, uint256, uint256) { + return buyWithPOLYRateLimited(_beneficiary, _investedPOLY, 0); } - function buyWithUSD(address _beneficiary, uint256 _investedDAI) external { - buyWithUSDRateLimited(_beneficiary, _investedDAI, 0); + function buyWithUSD(address _beneficiary, uint256 _investedSC, IERC20 _usdToken) external returns (uint256, uint256, uint256) { + return buyWithUSDRateLimited(_beneficiary, _investedSC, 0, _usdToken); } /** @@ -332,7 +369,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _beneficiary Address where security tokens will be sent * @param _minTokens Minumum number of tokens to buy or else revert */ - function buyWithETHRateLimited(address _beneficiary, uint256 _minTokens) public payable validETH { + function buyWithETHRateLimited(address _beneficiary, uint256 _minTokens) public payable validETH returns (uint256, uint256, uint256) { uint256 rate = getRate(FundRaiseType.ETH); uint256 initialMinted = getTokensMinted(); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, msg.value, rate, FundRaiseType.ETH); @@ -345,6 +382,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { // Refund excess ETH to investor wallet msg.sender.transfer(msg.value.sub(spentValue)); emit FundsReceived(msg.sender, _beneficiary, spentUSD, FundRaiseType.ETH, msg.value, spentValue, rate); + return (spentUSD, spentValue, getTokensMinted().sub(initialMinted)); } /** @@ -353,22 +391,24 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @param _investedPOLY Amount of POLY invested * @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); + function buyWithPOLYRateLimited(address _beneficiary, uint256 _investedPOLY, uint256 _minTokens) public validPOLY returns (uint256, uint256, uint256) { + return _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(address(_usdToken)) returns (uint256, uint256, uint256) + { + return _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 returns (uint256, uint256, uint256) { uint256 initialMinted = getTokensMinted(); uint256 rate = getRate(_fundRaiseType); (uint256 spentUSD, uint256 spentValue) = _buyTokens(_beneficiary, _tokenAmount, rate, _fundRaiseType); @@ -376,28 +416,29 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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"); + 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); + return (spentUSD, spentValue, getTokensMinted().sub(initialMinted)); } /** * @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, uint256 _investmentValue, uint256 _rate, FundRaiseType _fundRaiseType - ) - internal - nonReentrant - whenNotPaused - returns(uint256 spentUSD, uint256 spentValue) + ) + internal + whenNotPaused + returns(uint256 spentUSD, uint256 spentValue) { if (!allowBeneficialInvestments) { require(_beneficiary == msg.sender, "Beneficiary != funder"); @@ -410,19 +451,22 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { bool gotoNextTier; uint256 tempSpentUSD; // Update current tier if needed - if (currentTier != i) currentTier = i; + if (currentTier != i) + currentTier = i; // If there are tokens remaining, process investment if (tiers[i].mintedTotal < tiers[i].tokenTotal) { (tempSpentUSD, gotoNextTier) = _calculateTier(_beneficiary, i, allowedUSD.sub(spentUSD), _fundRaiseType); spentUSD = spentUSD.add(tempSpentUSD); // If all funds have been spent, exit the loop - if (!gotoNextTier) break; + if (!gotoNextTier) + break; } } // Modify storage if (spentUSD > 0) { - if (investorInvestedUSD[_beneficiary] == 0) investorCount = investorCount + 1; + if (investorInvestedUSD[_beneficiary] == 0) + investorCount = investorCount + 1; investorInvestedUSD[_beneficiary] = investorInvestedUSD[_beneficiary].add(spentUSD); fundsRaisedUSD = fundsRaisedUSD.add(spentUSD); } @@ -430,72 +474,39 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { spentValue = DecimalMath.div(spentUSD, _rate); } - /** - * @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 || _fundRaiseType == FundRaiseType.ETH, - "Invalid raise type" - ); - uint256 rate = getRate(_fundRaiseType); - 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++) { - 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, allowedUSD.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.div(spentUSD, rate); - } - function _buyTokensChecks( - address _beneficiary, - uint256 _investmentValue, + address _beneficiary, + uint256 _investmentValue, uint256 investedUSD - ) - internal - view - returns(uint256 netInvestedUSD) + ) + internal + view + returns(uint256 netInvestedUSD) { require(isOpen(), "STO not open"); - require(_investmentValue > 0, "No funds were sent"); + require(_investmentValue > 0, "No funds sent"); // Check for minimum investment - require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Total investment < minimumInvestmentUSD"); + require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Investment < min"); 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] - ); + if (investedUSD.add(investorInvestedUSD[_beneficiary]) > investorLimitUSD) + netInvestedUSD = investorLimitUSD.sub(investorInvestedUSD[_beneficiary]); } } - function _calculateTier(address _beneficiary, uint256 _tier, uint256 _investedUSD, FundRaiseType _fundRaiseType) internal returns( - uint256 spentUSD, - bool gotoNextTier - ) { + function _calculateTier( + address _beneficiary, + uint256 _tier, + uint256 _investedUSD, + FundRaiseType _fundRaiseType + ) + internal + returns(uint256 spentUSD, bool gotoNextTier) + { // First purchase any discounted tokens if POLY investment uint256 tierSpentUSD; uint256 tierPurchasedTokens; @@ -505,102 +516,36 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { 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, gotoNextTier) = _purchaseTier( - _beneficiary, - tierData.rateDiscountPoly, - totalRemaining, - investedUSD, - _tier - ); - else (spentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier( - _beneficiary, - tierData.rateDiscountPoly, - discountRemaining, - investedUSD, - _tier - ); + if (totalRemaining < discountRemaining) + (spentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier(_beneficiary, tierData.rateDiscountPoly, totalRemaining, investedUSD, _tier); + else + (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); 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 && (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly)) { - (tierSpentUSD, tierPurchasedTokens, gotoNextTier) = _purchaseTier( - _beneficiary, - tierData.rate, - tierData.tokenTotal.sub(tierData.mintedTotal), - investedUSD, - _tier - ); + if (investedUSD > 0 && + tierData.tokenTotal.sub(tierData.mintedTotal) > 0 && + (_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); tierData.minted[uint8(_fundRaiseType)] = tierData.minted[uint8(_fundRaiseType)].add(tierPurchasedTokens); tierData.mintedTotal = tierData.mintedTotal.add(tierPurchasedTokens); } } - 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 && (_fundRaiseType != FundRaiseType.POLY || tierData.tokensDiscountPoly <= tierData.mintedDiscountPoly)) { - (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, uint256 _tierRemaining, uint256 _investedUSD, uint256 _tier - ) - internal - returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) - { - (spentUSD, purchasedTokens, gotoNextTier) = _purchaseTierAmount(_tierPrice, _tierRemaining, _investedUSD); - if (purchasedTokens > 0) { - 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) + ) + internal + returns(uint256 spentUSD, uint256 purchasedTokens, bool gotoNextTier) { uint256 maximumTokens = DecimalMath.div(_investedUSD, _tierPrice); uint256 granularity = ISecurityToken(securityToken).granularity(); @@ -618,6 +563,10 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { spentUSD = DecimalMath.mul(maximumTokens, _tierPrice); purchasedTokens = maximumTokens; } + if (purchasedTokens > 0) { + require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Mint failed"); + emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); + } } ///////////// @@ -629,12 +578,9 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @return bool Whether the STO is accepting investments */ 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()) return false; + /*solium-disable-next-line security/no-block-members*/ + if (isFinalized || now < startTime || now >= endTime || capReached()) + return false; return true; } @@ -642,7 +588,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @notice Checks whether the cap has been reached. * @return bool Whether the cap was reached */ - function capReached() public view returns(bool) { + function capReached() public view returns (bool) { if (isFinalized) { return (finalAmountReturned == 0); } @@ -653,15 +599,13 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @dev returns current conversion rate of funds * @param _fundRaiseType Fund raise type to get rate of */ - function getRate(FundRaiseType _fundRaiseType) public view returns(uint256) { + function getRate(FundRaiseType _fundRaiseType) public view returns (uint256) { if (_fundRaiseType == FundRaiseType.ETH) { 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) { - return 1 * 10 ** 18; - } else { - revert("Incorrect funding"); + } else if (_fundRaiseType == FundRaiseType.SC) { + return 10**18; } } @@ -672,8 +616,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @return uint256 Value in USD */ function convertToUSD(FundRaiseType _fundRaiseType, uint256 _amount) public view returns(uint256) { - uint256 rate = getRate(_fundRaiseType); - return DecimalMath.mul(_amount, rate); + return DecimalMath.mul(_amount, getRate(_fundRaiseType)); } /** @@ -683,48 +626,38 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @return uint256 Value in ETH or POLY */ function convertFromUSD(FundRaiseType _fundRaiseType, uint256 _amount) public view returns(uint256) { - uint256 rate = getRate(_fundRaiseType); - return DecimalMath.div(_amount, rate); + return DecimalMath.div(_amount, getRate(_fundRaiseType)); } /** * @notice Return the total no. of tokens sold * @return uint256 Total number of tokens sold */ - function getTokensSold() external view returns (uint256) { - return _getTokensSold(); - } - - function _getTokensSold() internal view returns (uint256) { + function getTokensSold() public view returns (uint256) { if (isFinalized) return totalTokensSold; - else - return getTokensMinted(); + return getTokensMinted(); } /** * @notice Return the total no. of tokens minted * @return uint256 Total number of tokens minted */ - function getTokensMinted() public view returns(uint256) { - uint256 tokensMinted; + function getTokensMinted() public view returns (uint256 tokensMinted) { for (uint256 i = 0; i < tiers.length; i++) { tokensMinted = tokensMinted.add(tiers[i].mintedTotal); } - return tokensMinted; } /** * @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) { - uint256 tokensSold; + function getTokensSoldFor(FundRaiseType _fundRaiseType) external view returns (uint256 tokensSold) { for (uint256 i = 0; i < tiers.length; i++) { tokensSold = tokensSold.add(tiers[i].minted[uint8(_fundRaiseType)]); } - return tokensSold; } /** @@ -732,12 +665,11 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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[] memory) { - require(_tier < tiers.length, "Invalid tier"); + function getTokensMintedByTier(uint256 _tier) external view returns(uint256[] memory) { 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; } @@ -746,12 +678,11 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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) { - require(_tier < tiers.length, "Incorrect tier"); + function getTokensSoldByTier(uint256 _tier) external view returns (uint256) { 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; } @@ -759,15 +690,22 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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; } + /** + * @notice Return the usd tokens accepted by the STO + * @return address[] usd tokens + */ + function getUsdTokens() external view returns (address[] memory) { + return usdTokens; + } + /** * @notice Return the permissions flag that are associated with STO */ - function getPermissions() public view returns(bytes32[] memory) { - bytes32[] memory allPermissions = new bytes32[](0); + function getPermissions() public view returns(bytes32[] memory allPermissions) { return allPermissions; } @@ -781,30 +719,19 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, 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[] memory, - uint256[] memory, - uint256, - uint256, - uint256, - bool[] memory - ) - { + function getSTODetails() external view returns(uint256, uint256, uint256, uint256[] memory, uint256[] memory, uint256, uint256, uint256, bool[] memory) { uint256[] memory cap = new uint256[](tiers.length); uint256[] memory rate = new uint256[](tiers.length); - for (uint256 i = 0; i < tiers.length; i++) { + 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)]; + _fundRaiseTypes[2] = fundRaiseTypes[uint8(FundRaiseType.SC)]; return ( startTime, endTime, @@ -813,7 +740,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { rate, fundsRaisedUSD, investorCount, - _getTokensSold(), + getTokensSold(), _fundRaiseTypes ); } @@ -823,7 +750,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO, ReentrancyGuard { * @return bytes4 Configure function signature */ function getInitFunction() public pure returns(bytes4) { - return 0xb0ff041e; + return this.configure.selector; } function _getOracle(bytes32 _currency, bytes32 _denominatedCurrency) internal view returns(address) { diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4ad558144..e691bce09 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -22,9 +22,9 @@ contract USDTieredSTOFactory is ModuleFactory { uint256 _usageCost, uint256 _subscriptionCost, address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "0x address is not allowed"); logicContract = _logicContract; @@ -52,7 +52,7 @@ contract USDTieredSTOFactory is ModuleFactory { require(success, "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/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 756a9ce7c..9901ba714 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -2,6 +2,7 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; import "./CountTransferManagerStorage.sol"; +import "../../interfaces/ISecurityToken.sol"; /** * @title Transfer Manager for limiting maximum number of token holders @@ -29,9 +30,9 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { uint256 _amount, bytes calldata /* _data */, bool /* _isTransfer */ - ) - external - returns(Result) + ) + external + returns(Result) { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index ec88dadc9..b4889dd36 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,8 +1,9 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; -import "./GeneralTransferManagerStorage.sol"; +import "../../storage/GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../../interfaces/ISecurityToken.sol"; /** * @title Transfer Manager module for core transfer validation functionality @@ -31,9 +32,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage // 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, @@ -174,7 +175,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage //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) && + 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; @@ -194,9 +195,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO - ) - public - withPerm(WHITELIST) + ) + public + withPerm(WHITELIST) { _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -272,8 +273,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint8 _v, bytes32 _r, bytes32 _s - ) - public + ) + public { /*solium-disable-next-line security/no-block-members*/ require(_validFrom <= now, "ValidFrom is too early"); diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 3bc258c60..167c80ac6 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -5,7 +5,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./ManualApprovalTransferManagerStorage.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 ManualApprovalTransferManagerStorage, TransferManager { using SafeMath for uint256; @@ -15,14 +15,17 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, address indexed _to, uint256 _allowance, uint256 _expiryTime, + bytes32 _description, address indexed _addedBy ); - event AddManualBlocking( + event ModifyManualApproval( address indexed _from, address indexed _to, uint256 _expiryTime, - address indexed _addedBy + uint256 _allowance, + bytes32 _description, + address indexed _edittedBy ); event RevokeManualApproval( @@ -31,12 +34,6 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, address indexed _addedBy ); - event RevokeManualBlocking( - address indexed _from, - address indexed _to, - address indexed _addedBy - ); - /** * @notice Constructor * @param _securityToken Address of the security token @@ -52,7 +49,8 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, 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 @@ -64,22 +62,19 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, uint256 _amount, bytes calldata, /* _data */ bool _isTransfer - ) - external - returns(Result) + ) + external + 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 (!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) { - manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount); + approval.allowance = approval.allowance.sub(_amount); } return Result.VALID; } @@ -93,29 +88,155 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, * @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) 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"); - /*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); + require(_allowance > 0, "Invalid allowance"); + 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; + emit AddManualApproval(_from, _to, _allowance, _expiryTime, _description, 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 + * @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 _expiryTimes is the array of the times until which eath transfer is allowed + * @param _descriptions is the description array for these manual approvals */ - function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) { + function addManualApprovalMulti( + address[] calldata _from, + address[] calldata _to, + uint256[] calldata _allowances, + uint256[] calldata _expiryTimes, + bytes32[] calldata _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 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 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(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists"); - manualBlockings[_from][_to] = ManualBlocking(_expiryTime); - emit AddManualBlocking(_from, _to, _expiryTime, msg.sender); + 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; + 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; + } else { + newAllowance = currentAllowance.sub(_changedAllowance); + approval.allowance = newAllowance; + } + } else { + // No change in the Allowance + newAllowance = currentAllowance; + } + // Greedy storage technique + if (approval.expiryTime != _expiryTime) { + approval.expiryTime = _expiryTime; + } + if (approval.description != _description) { + approval.description = _description; + } + emit ModifyManualApproval(_from, _to, _expiryTime, newAllowance, _description, 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[] memory _from, + address[] memory _to, + uint256[] memory _expiryTimes, + uint256[] memory _changedAllowances, + bytes32[] memory _descriptions, + uint8[] memory _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]); + } } /** @@ -123,21 +244,151 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, * @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); + } + + function _revokeManualApproval(address _from, address _to) internal { + require(approvalIndex[_from][_to] != 0, "Approval not exist"); + + // 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; + } + delete approvalIndex[_from][_to]; + approvals.length--; 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 + * @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 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); + function revokeManualApprovalMulti(address[] calldata _from, address[] calldata _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[] memory _from, + address[] memory _to, + uint256[] memory _expiryTimes, + uint256[] memory _allowances, + bytes32[] memory _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 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[] memory, address[] memory, uint256[] memory, uint256[] memory, bytes32[] memory) { + 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 ++; + } + + 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 (uint256 i = 0; i < approvals.length; i++) { + if ((approvals[i].from == _user || approvals[i].to == _user) + && approvals[i].expiryTime >= now) { + + 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 (from, to, allowance, expiryTime, description); + } + + /** + * @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 (approvalIndex[_from][_to] != 0) { + uint256 index = approvalIndex[_from][_to] - 1; + 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 getTotalApprovalsLength() external view returns(uint256) { + 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[] memory, address[] memory, uint256[] memory, uint256[] memory, bytes32[] memory) { + 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); + } /** diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index ac4ac109c..6d50e9e2f 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -22,15 +22,15 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { uint256 _usageCost, uint256 _subscriptionCost, address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ) + public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) { require(_logicContract != address(0), "Invalid address"); - version = "2.0.1"; + version = "2.1.0"; 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)); logicContract = _logicContract; @@ -42,9 +42,9 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { */ function deploy( bytes calldata /* _data */ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); ManualApprovalTransferManagerProxy manualTransferManager = new ManualApprovalTransferManagerProxy(msg.sender, polyToken, logicContract); @@ -67,7 +67,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { */ function getInstructions() external view returns(string memory) { /*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/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol index 6f94fbac6..29671ff42 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol @@ -15,19 +15,15 @@ contract ManualApprovalTransferManagerStorage { //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; } - //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; + mapping (address => mapping (address => uint256)) public approvalIndex; + // An array to track all approvals + ManualApproval[] public approvals; } diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index 43c4a6f61..cdd0cc073 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -40,9 +40,9 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer uint256 _amount, bytes calldata, /* _data */ bool /* _isTransfer */ - ) - external - returns(Result) + ) + external + returns(Result) { if (!paused) { if (_from == address(0) && allowPrimaryIssuance) { @@ -52,8 +52,8 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer if (whitelist[_to]) { return Result.NA; } - uint256 newBalance = ISecurityToken(securityToken).balanceOf(_to).add(_amount); - if (newBalance.mul(uint256(10) ** 18).div(ISecurityToken(securityToken).totalSupply()) > maxHolderPercentage) { + uint256 newBalance = IERC20(securityToken).balanceOf(_to).add(_amount); + if (newBalance.mul(uint256(10) ** 18).div(IERC20(securityToken).totalSupply()) > maxHolderPercentage) { return Result.INVALID; } return Result.NA; diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol new file mode 100644 index 000000000..2a9bd7803 --- /dev/null +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -0,0 +1,1095 @@ +pragma solidity ^0.5.0; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../../libraries/BokkyPooBahsDateTimeLibrary.sol"; +import "../../libraries/VolumeRestrictionLib.sol"; +import "./TransferManager.sol"; + +contract VolumeRestrictionTM is VolumeRestrictionTMStorage, TransferManager { + using SafeMath for uint256; + + // permission definition + bytes32 public constant ADMIN = "ADMIN"; + + // 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 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, + 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 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // 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 global restriction is added + event AddDefaultRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the new daily (Default) restriction is added + event AddDefaultDailyRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when default restriction get modified + event ModifyDefaultRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when daily default restriction get modified + event ModifyDefaultDailyRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _typeOfRestriction + ); + // Emit when the individual restriction gets removed + event IndividualRestrictionRemoved(address indexed _holder); + // Emit when individual daily restriction removed + event IndividualDailyRestrictionRemoved(address indexed _holder); + // Emit when the default restriction gets removed + event DefaultRestrictionRemoved(); + // Emit when the daily default restriction gets removed + event DefaultDailyRestrictionRemoved(); + + /** + * @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 memory /*_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) && exemptions.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 + if ((individualRestrictions.individualRestriction[_from].endTime >= now && individualRestrictions.individualRestriction[_from].startTime <= now) + || (individualRestrictions.individualDailyRestriction[_from].endTime >= now && individualRestrictions.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 ((globalRestrictions.defaultRestriction.endTime >= now && globalRestrictions.defaultRestriction.startTime <= now) + || (globalRestrictions.defaultDailyRestriction.endTime >= now && globalRestrictions.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 + */ + function changeExemptWalletList(address _wallet, bool _change) public withPerm(ADMIN) { + require(_wallet != address(0)); + require((exemptions.exemptIndex[_wallet] == 0) == _change); + if (_change) { + exemptions.exemptAddresses.push(_wallet); + exemptions.exemptIndex[_wallet] = exemptions.exemptAddresses.length; + } else { + exemptions.exemptAddresses[exemptions.exemptIndex[_wallet] - 1] = exemptions.exemptAddresses[exemptions.exemptAddresses.length - 1]; + exemptions.exemptIndex[exemptions.exemptAddresses[exemptions.exemptIndex[_wallet] - 1]] = exemptions.exemptIndex[_wallet]; + delete exemptions.exemptIndex[_wallet]; + exemptions.exemptAddresses.length --; + } + 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 _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 addIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + public + withPerm(ADMIN) + { + require( + individualRestrictions.individualRestriction[_holder].endTime < now, + "Not Allowed" + ); + if (_startTime == 0) { + _startTime = now; + } + require(_holder != address(0) && exemptions.exemptIndex[_holder] == 0, "Invalid address"); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + + if (individualRestrictions.individualRestriction[_holder].endTime != 0) { + removeIndividualRestriction(_holder); + } + individualRestrictions.individualRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + VolumeRestrictionLib.addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.MultipleDays), individualRestrictions.individualRestriction[_holder].endTime); + emit AddIndividualRestriction( + _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 + * @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 + ) + public + withPerm(ADMIN) + { + if (_startTime == 0) { + _startTime = now; + } + require( + individualRestrictions.individualDailyRestriction[_holder].endTime < now, + "Not Allowed" + ); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, now); + if (individualRestrictions.individualDailyRestriction[_holder].endTime != 0) { + removeIndividualDailyRestriction(_holder); + } + individualRestrictions.individualDailyRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + VolumeRestrictionLib.addRestrictionData(holderData, _holder, uint8(TypeOfPeriod.OneDay), individualRestrictions.individualRestriction[_holder].endTime); + 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 + * @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[] memory _holders, + uint256[] memory _allowedTokens, + uint256[] memory _startTimes, + uint256[] memory _endTimes, + uint256[] memory _restrictionTypes + ) + public + { + //NB - we duplicate _startTimes below to allow function reuse + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + 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 + * @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 _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) + */ + function addIndividualRestrictionMulti( + address[] memory _holders, + uint256[] memory _allowedTokens, + uint256[] memory _startTimes, + uint256[] memory _rollingPeriodInDays, + uint256[] memory _endTimes, + uint256[] memory _restrictionTypes + ) + public + { + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + for (uint256 i = 0; i < _holders.length; i++) { + addIndividualRestriction( + _holders[i], + _allowedTokens[i], + _startTimes[i], + _rollingPeriodInDays[i], + _endTimes[i], + _restrictionTypes[i] + ); + } + } + + /** + * @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 addDefaultRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } + require( + globalRestrictions.defaultRestriction.endTime < now, + "Not Allowed" + ); + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + globalRestrictions.defaultRestriction = VolumeRestriction( + _allowedTokens, + startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddDefaultRestriction( + _allowedTokens, + startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @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 addDefaultDailyRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } + require( + globalRestrictions.defaultDailyRestriction.endTime < now, + "Not Allowed" + ); + _checkInputParams(_allowedTokens, startTime, 1, _endTime, _restrictionType, now); + globalRestrictions.defaultDailyRestriction = VolumeRestriction( + _allowedTokens, + startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit AddDefaultDailyRestriction( + _allowedTokens, + startTime, + 1, + _endTime, + _restrictionType + ); + } + + /** + * @notice use to remove the individual restriction for a given address + * @param _holder Address of the user + */ + function removeIndividualRestriction(address _holder) public withPerm(ADMIN) { + require(_holder != address(0)); + require(individualRestrictions.individualRestriction[_holder].endTime != 0); + individualRestrictions.individualRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.OneDay)); + bucketData.userToBucket[_holder].lastTradedDayTime = 0; + bucketData.userToBucket[_holder].sumOfLastPeriod = 0; + bucketData.userToBucket[_holder].daysCovered = 0; + emit IndividualRestrictionRemoved(_holder); + } + + /** + * @notice use to remove the individual restriction for a given address + * @param _holders Array of address of the user + */ + function removeIndividualRestrictionMulti(address[] calldata _holders) external { + for (uint256 i = 0; i < _holders.length; i++) { + removeIndividualRestriction(_holders[i]); + } + } + + /** + * @notice use to remove the individual daily restriction for a given address + * @param _holder Address of the user + */ + function removeIndividualDailyRestriction(address _holder) public withPerm(ADMIN) { + require(_holder != address(0)); + require(individualRestrictions.individualDailyRestriction[_holder].endTime != 0); + individualRestrictions.individualDailyRestriction[_holder] = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + VolumeRestrictionLib.deleteHolderFromList(holderData, _holder, uint8(TypeOfPeriod.MultipleDays)); + bucketData.userToBucket[_holder].dailyLastTradedDayTime = 0; + emit IndividualDailyRestrictionRemoved(_holder); + } + + /** + * @notice use to remove the individual daily restriction for a given address + * @param _holders Array of address of the user + */ + function removeIndividualDailyRestrictionMulti(address[] calldata _holders) external { + for (uint256 i = 0; i < _holders.length; i++) { + removeIndividualDailyRestriction(_holders[i]); + } + } + + /** + * @notice Use to remove the default restriction + */ + function removeDefaultRestriction() public withPerm(ADMIN) { + require(globalRestrictions.defaultRestriction.endTime != 0); + globalRestrictions.defaultRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + emit DefaultRestrictionRemoved(); + } + + /** + * @notice Use to remove the daily default restriction + */ + function removeDefaultDailyRestriction() external withPerm(ADMIN) { + require(globalRestrictions.defaultDailyRestriction.endTime != 0); + globalRestrictions.defaultDailyRestriction = VolumeRestriction(0, 0, 0, 0, RestrictionType(0)); + emit DefaultDailyRestrictionRemoved(); + } + + /** + * @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 _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 modifyIndividualRestriction( + address _holder, + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + public + withPerm(ADMIN) + { + if (_startTime == 0) { + _startTime = now; + } + require(individualRestrictions.individualRestriction[_holder].startTime > now, "Not Allowed"); + _checkInputParams(_allowedTokens, _startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + individualRestrictions.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 + * @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. + * @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 + ) + public + withPerm(ADMIN) + { + if (_startTime == 0) { + _startTime = now; + } + uint checkTime = (individualRestrictions.individualDailyRestriction[_holder].startTime <= now ? individualRestrictions.individualDailyRestriction[_holder].startTime : now); + _checkInputParams(_allowedTokens, _startTime, 1, _endTime, _restrictionType, checkTime); + individualRestrictions.individualDailyRestriction[_holder] = VolumeRestriction( + _allowedTokens, + _startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyIndividualDailyRestriction( + _holder, + _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 + * @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[] memory _holders, + uint256[] memory _allowedTokens, + uint256[] memory _startTimes, + uint256[] memory _endTimes, + uint256[] memory _restrictionTypes + ) + public + { + //NB - we duplicate _startTimes below to allow function reuse + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _startTimes, _endTimes, _restrictionTypes); + 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 + * @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 _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) + */ + function modifyIndividualRestrictionMulti( + address[] memory _holders, + uint256[] memory _allowedTokens, + uint256[] memory _startTimes, + uint256[] memory _rollingPeriodInDays, + uint256[] memory _endTimes, + uint256[] memory _restrictionTypes + ) + public + { + VolumeRestrictionLib._checkLengthOfArray(_holders, _allowedTokens, _startTimes, _rollingPeriodInDays, _endTimes, _restrictionTypes); + for (uint256 i = 0; i < _holders.length; i++) { + modifyIndividualRestriction( + _holders[i], + _allowedTokens[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 _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 modifyDefaultRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodInDays, + uint256 _endTime, + uint256 _restrictionType + ) + external + withPerm(ADMIN) + { + require(globalRestrictions.defaultRestriction.startTime > now, "Not Allowed"); + uint256 startTime = _startTime; + if (_startTime == 0) { + startTime = now; + } + _checkInputParams(_allowedTokens, startTime, _rollingPeriodInDays, _endTime, _restrictionType, now); + globalRestrictions.defaultRestriction = VolumeRestriction( + _allowedTokens, + startTime, + _rollingPeriodInDays, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyDefaultRestriction( + _allowedTokens, + startTime, + _rollingPeriodInDays, + _endTime, + _restrictionType + ); + } + + /** + * @notice Use to modify the daily default restriction for all token holder + * @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. + * @param _restrictionType It will be 0 or 1 (i.e 0 for fixed while 1 for Percentage) + */ + function modifyDefaultDailyRestriction( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _endTime, + uint256 _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, + (globalRestrictions.defaultDailyRestriction.startTime <= now ? globalRestrictions.defaultDailyRestriction.startTime : now) + ); + globalRestrictions.defaultDailyRestriction = VolumeRestriction( + _allowedTokens, + startTime, + 1, + _endTime, + RestrictionType(_restrictionType) + ); + emit ModifyDefaultDailyRestriction( + _allowedTokens, + startTime, + 1, + _endTime, + _restrictionType + ); + } + + /** + * @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 + BucketDetails storage bucketDetails = bucketData.defaultUserToBucket[_from]; + uint256 daysCovered = globalRestrictions.defaultRestriction.rollingPeriodInDays; + uint256 fromTimestamp = 0; + uint256 sumOfLastPeriod = 0; + uint256 dailyTime = 0; + bool allowedDefault = true; + bool allowedDaily; + if (globalRestrictions.defaultRestriction.endTime >= now && globalRestrictions.defaultRestriction.startTime <= now) { + if (bucketDetails.lastTradedDayTime < globalRestrictions.defaultRestriction.startTime) { + // It will execute when the txn is performed first time after the addition of individual restriction + fromTimestamp = globalRestrictions.defaultRestriction.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, globalRestrictions.defaultRestriction)) { + allowedDefault = false; + } + } + (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, globalRestrictions.defaultDailyRestriction); + + if (_isTransfer) { + _updateStorage( + _from, + _amount, + fromTimestamp, + sumOfLastPeriod, + daysCovered, + dailyTime, + globalRestrictions.defaultDailyRestriction.endTime, + true + ); + } + 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 = bucketData.userToBucket[_from]; + VolumeRestriction memory dailyRestriction = individualRestrictions.individualDailyRestriction[_from]; + VolumeRestriction memory restriction = individualRestrictions.individualRestriction[_from]; + uint256 daysCovered = restriction.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 memory 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 (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)); + // Assgining total sum traded on dailyLastTradedDayTime timestamp + txSumOfDay = bucketData.bucket[from][dailyLastTradedDayTime]; + return (_checkValidAmountToTransact(txSumOfDay, amount, restriction), dailyLastTradedDayTime); + } + return (true, dailyLastTradedDayTime); + } + + /// Internal function for the bucket check + function _bucketCheck( + uint256 _fromTime, + uint256 _diffDays, + address _from, + uint256 _rollingPeriodInDays, + BucketDetails memory _bucketDetails + ) + internal + view + returns (uint256, uint256, uint256) + { + 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++; + // 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(bucketData.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 + // 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); + } + + function _checkValidAmountToTransact( + uint256 _sumOfLastPeriod, + uint256 _amountToTransact, + VolumeRestriction memory _restriction + ) + internal + view + returns (bool) + { + uint256 _allowedAmount = 0; + if (_restriction.typeOfRestriction == RestrictionType.Percentage) { + _allowedAmount = (_restriction.allowedTokens.mul(IERC20(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, + uint256 _lastTradedDayTime, + uint256 _sumOfLastPeriod, + uint256 _daysCovered, + uint256 _dailyLastTradedDayTime, + uint256 _endTime, + bool isDefault + ) + internal + { + + if (isDefault){ + BucketDetails storage defaultUserToBucketDetails = bucketData.defaultUserToBucket[_from]; + _updateStorageActual(_from, _amount, _lastTradedDayTime, _sumOfLastPeriod, _daysCovered, _dailyLastTradedDayTime, _endTime, defaultUserToBucketDetails); + } + else { + BucketDetails storage userToBucketDetails = bucketData.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 + details.lastTradedDayTime = _lastTradedDayTime; + } + if (details.dailyLastTradedDayTime != _dailyLastTradedDayTime) { + // Assigning the latest transaction timestamp of the day + details.dailyLastTradedDayTime = _dailyLastTradedDayTime; + } + if (details.daysCovered != _daysCovered) { + details.daysCovered = _daysCovered; + } + + if (_amount != 0) { + if (_lastTradedDayTime !=0) { + details.sumOfLastPeriod = _sumOfLastPeriod.add(_amount); + // Increasing the total amount of the day by `_amount` + bucketData.bucket[_from][_lastTradedDayTime] = bucketData.bucket[_from][_lastTradedDayTime].add(_amount); + } + if ((_dailyLastTradedDayTime != _lastTradedDayTime) && _dailyLastTradedDayTime != 0 && now <= _endTime) { + // Increasing the total amount of the day by `_amount` + bucketData.bucket[_from][_dailyLastTradedDayTime] = bucketData.bucket[_from][_dailyLastTradedDayTime].add(_amount); + } + } + } + + function _checkInputParams( + uint256 _allowedTokens, + uint256 _startTime, + uint256 _rollingPeriodDays, + uint256 _endTime, + 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 { + require( + _allowedTokens > 0 && _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, + "Invalid times" + ); + } + + /** + * @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 getIndividualBucketDetailsToUser(address _user) public view returns(uint256, uint256, uint256, uint256) { + return( + bucketData.userToBucket[_user].lastTradedDayTime, + bucketData.userToBucket[_user].sumOfLastPeriod, + bucketData.userToBucket[_user].daysCovered, + bucketData.userToBucket[_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) public view returns(uint256, uint256, uint256, uint256) { + return( + bucketData.defaultUserToBucket[_user].lastTradedDayTime, + bucketData.defaultUserToBucket[_user].sumOfLastPeriod, + bucketData.defaultUserToBucket[_user].daysCovered, + bucketData.defaultUserToBucket[_user].dailyLastTradedDayTime + ); + } + + /** + * @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 getTotalTradedByUser(address _user, uint256 _at) external view returns(uint256) { + return bucketData.bucket[_user][_at]; + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns(bytes4) { + return bytes4(0); + } + + /** + * @notice Use to return the list of exempted addresses + */ + function getExemptAddress() external view returns(address[] memory) { + return exemptions.exemptAddresses; + } + + function getIndividualRestriction(address _investor) external view returns(uint256, uint256, uint256, uint256, RestrictionType) { + return _volumeRestrictionSplay(individualRestrictions.individualRestriction[_investor]); + } + + function getIndividualDailyRestriction(address _investor) external view returns(uint256, uint256, uint256, uint256, RestrictionType) { + return _volumeRestrictionSplay(individualRestrictions.individualDailyRestriction[_investor]); + } + + function getDefaultRestriction() external view returns(uint256, uint256, uint256, uint256, RestrictionType) { + return _volumeRestrictionSplay(globalRestrictions.defaultRestriction); + } + + function getDefaultDailyRestriction() external view returns(uint256, uint256, uint256, uint256, RestrictionType) { + return _volumeRestrictionSplay(globalRestrictions.defaultDailyRestriction); + } + + function _volumeRestrictionSplay(VolumeRestriction memory _volumeRestriction) internal pure returns(uint256, uint256, uint256, uint256, RestrictionType) { + return ( + _volumeRestriction.allowedTokens, + _volumeRestriction.startTime, + _volumeRestriction.rollingPeriodInDays, + _volumeRestriction.endTime, + _volumeRestriction.typeOfRestriction + ); + } + + /** + * @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 getRestrictionData() external view returns( + address[] memory allAddresses, + uint256[] memory allowedTokens, + uint256[] memory startTime, + uint256[] memory rollingPeriodInDays, + uint256[] memory endTime, + uint8[] memory typeOfRestriction + ) { + return VolumeRestrictionLib.getRestrictionData(holderData, individualRestrictions); + } + + + + /** + * @notice Returns the permissions flag that are associated with Percentage transfer Manager + */ + function getPermissions() public view returns(bytes32[] memory ) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = ADMIN; + return allPermissions; + } + +} diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol new file mode 100644 index 000000000..b105dba6f --- /dev/null +++ b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol @@ -0,0 +1,73 @@ +pragma solidity ^0.5.0; + +import "../../proxy/VolumeRestrictionTMProxy.sol"; +import "../ModuleFactory.sol"; + +/** + * @title Factory for deploying VolumeRestrictionTM module + */ +contract VolumeRestrictionTMFactory is ModuleFactory { + + address public logicContract; + + /** + * @notice Constructor + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public + ModuleFactory(_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; + } + + + /** + * @notice Used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes calldata /* _data */) external returns(address) { + address polyToken = _takeFee(); + address volumeRestrictionTransferManager = address(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; + } + + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[] memory) { + 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 memory) { + /*solium-disable-next-line max-len*/ + 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[] memory) { + 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/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol index efd4a1445..5dc0c8e63 100644 --- a/contracts/proxy/ERC20DividendCheckpointProxy.sol +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -17,12 +17,12 @@ contract ERC20DividendCheckpointProxy is ERC20DividendCheckpointStorage, Dividen * @param _implementation representing the address of the new implementation to be set */ constructor( - address _securityToken, - address _polyAddress, + address _securityToken, + address _polyAddress, address _implementation - ) - public - ModuleStorage(_securityToken, _polyAddress) + ) + 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 index e03ccbbad..381d71d27 100644 --- a/contracts/proxy/EtherDividendCheckpointProxy.sol +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -16,12 +16,12 @@ contract EtherDividendCheckpointProxy is DividendCheckpointStorage, ModuleStorag * @param _implementation representing the address of the new implementation to be set */ constructor ( - address _securityToken, - address _polyAddress, + address _securityToken, + address _polyAddress, address _implementation - ) - public - ModuleStorage(_securityToken, _polyAddress) + ) + 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 index c8c8ddcc1..0a4adbc08 100644 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.0; -import "../modules/TransferManager/GeneralTransferManagerStorage.sol"; +import "../storage/GeneralTransferManagerStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "../modules/ModuleStorage.sol"; @@ -16,12 +16,12 @@ contract GeneralTransferManagerProxy is GeneralTransferManagerStorage, ModuleSto * @param _implementation representing the address of the new implementation to be set */ constructor( - address _securityToken, - address _polyAddress, + address _securityToken, + address _polyAddress, address _implementation - ) - public - ModuleStorage(_securityToken, _polyAddress) + ) + public + ModuleStorage(_securityToken, _polyAddress) { require(_implementation != address(0), "Implementation address should not be 0x"); __implementation = _implementation; diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol index 290cea83d..1f5a1087a 100644 --- a/contracts/proxy/USDTieredSTOProxy.sol +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -1,6 +1,6 @@ pragma solidity ^0.5.0; -import "../modules/STO/USDTieredSTOStorage.sol"; +import "../storage/USDTieredSTOStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; diff --git a/contracts/proxy/VestingEscrowWalletProxy.sol b/contracts/proxy/VestingEscrowWalletProxy.sol new file mode 100644 index 000000000..a69463084 --- /dev/null +++ b/contracts/proxy/VestingEscrowWalletProxy.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.5.0; + +import "../storage/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 diff --git a/contracts/proxy/VolumeRestrictionTMProxy.sol b/contracts/proxy/VolumeRestrictionTMProxy.sol new file mode 100644 index 000000000..ce1356904 --- /dev/null +++ b/contracts/proxy/VolumeRestrictionTMProxy.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.5.0; + +import "../storage/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/contracts/storage/EternalStorage.sol b/contracts/storage/EternalStorage.sol index 114f0125c..40175f31d 100644 --- a/contracts/storage/EternalStorage.sol +++ b/contracts/storage/EternalStorage.sol @@ -56,38 +56,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 memory) { - return stringStorage[_key]; - } - - function getBytes32(bytes32 _key) internal view returns(bytes32) { - return bytes32Storage[_key]; - } - //////////////////////////// // deleteArray functions //////////////////////////// @@ -189,19 +157,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[] memory) { + function getArrayAddress(bytes32 _key) public view returns(address[] memory) { return addressArrayStorage[_key]; } - function getArrayBytes32(bytes32 _key) internal view returns(bytes32[] memory) { + function getArrayBytes32(bytes32 _key) public view returns(bytes32[] memory) { return bytes32ArrayStorage[_key]; } - function getArrayString(bytes32 _key) internal view returns(string[] memory) { - return stringArrayStorage[_key]; - } - - function getArrayUint(bytes32 _key) internal view returns(uint[] memory) { + function getArrayUint(bytes32 _key) public view returns(uint[] memory) { return uintArrayStorage[_key]; } @@ -229,31 +193,37 @@ contract EternalStorage { stringArrayStorage[_key][_index] = _value; } - ///////////////////////////// /// 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 memory) { + function getStringValue(bytes32 _variable) public view returns(string memory) { 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 memory) { + function getBytesValue(bytes32 _variable) public view returns(bytes memory) { return bytesStorage[_variable]; } diff --git a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol similarity index 96% rename from contracts/modules/TransferManager/GeneralTransferManagerStorage.sol rename to contracts/storage/GeneralTransferManagerStorage.sol index b9add9a57..83418fc2a 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -36,7 +36,7 @@ contract GeneralTransferManagerStorage { // An address can only send / receive tokens once their corresponding uint256 > block.number // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping(address => TimeRestriction) public whitelist; + mapping (address => TimeRestriction) public whitelist; // Map of used nonces by customer mapping(address => mapping(uint256 => bool)) public nonceMap; diff --git a/contracts/modules/STO/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol similarity index 67% rename from contracts/modules/STO/USDTieredSTOStorage.sol rename to contracts/storage/USDTieredSTOStorage.sol index a1c6f88ba..267df4f58 100644 --- a/contracts/modules/STO/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -10,6 +10,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; // How many token units a buyer gets per USD in this tier (multiplied by 10**18) when investing in POLY up to tokensDiscountPoly @@ -26,43 +27,57 @@ contract USDTieredSTOStorage { uint256 mintedDiscountPoly; } - mapping(bytes32 => mapping(bytes32 => string)) oracleKeys; + 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; + } - IERC20 public usdToken; + mapping(bytes32 => mapping(bytes32 => string)) oracleKeys; // Determine whether users can invest on behalf of a beneficiary - bool public allowBeneficialInvestments = false; + bool public allowBeneficialInvestments; // Whether or not the STO has been finalized bool public isFinalized; - // Address where ETH, POLY & DAI funds are delivered - address payable public wallet; - // Address of issuer reserve wallet for unsold tokens address public reserveWallet; + // List of stable coin addresses + address[] internal usdTokens; + // Current tier uint256 public currentTier; // Amount of USD funds raised uint256 public fundsRaisedUSD; + // Amount of stable coins raised + mapping (address => uint256) public stableCoinsRaised; + // 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; + // Accredited & non-accredited investor data + mapping (address => Investor) public investors; + + // List of active stable coin addresses + mapping (address => bool) internal 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; diff --git a/contracts/storage/VestingEscrowWalletStorage.sol b/contracts/storage/VestingEscrowWalletStorage.sol new file mode 100644 index 000000000..f3752ad7f --- /dev/null +++ b/contracts/storage/VestingEscrowWalletStorage.sol @@ -0,0 +1,54 @@ +pragma solidity ^0.5.0; + +/** + * @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; + // 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 + 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; + // 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; + // 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/storage/VolumeRestrictionTMStorage.sol b/contracts/storage/VolumeRestrictionTMStorage.sol new file mode 100644 index 000000000..0c88cbd65 --- /dev/null +++ b/contracts/storage/VolumeRestrictionTMStorage.sol @@ -0,0 +1,86 @@ +pragma solidity ^0.5.0; + +/** + * @title Storage layout for VolumeRestrictionTM + */ +contract VolumeRestrictionTMStorage { + + enum RestrictionType { Fixed, Percentage } + + 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; + } + + // Restricted data (refernce from the VolumeRestrictionLib library ) + RestrictedData holderData; + + 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 IndividualRestrictions { + // Restriction stored corresponds to a particular token holder + mapping(address => VolumeRestriction) individualRestriction; + // Daily restriction stored corresponds to a particular token holder + mapping(address => VolumeRestriction) individualDailyRestriction; + } + + // Individual and daily restrictions for investors + IndividualRestrictions individualRestrictions; + + struct GlobalRestrictions { + // Global restriction that applies to all token holders + VolumeRestriction defaultRestriction; + // Daily global restriction that applies to all token holders (Total ST traded daily is restricted) + VolumeRestriction defaultDailyRestriction; + } + + // Individual and daily restrictions for investors + GlobalRestrictions globalRestrictions; + + 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; + } + + struct BucketData { + // Storing _from => day's timestamp => total amount transact in a day --individual + mapping(address => mapping(uint256 => uint256)) bucket; + // Storing the information that used to validate the transaction + mapping(address => BucketDetails) userToBucket; + // Storing the information related to default restriction + mapping(address => BucketDetails) defaultUserToBucket; + } + + BucketData bucketData; + + // Hold exempt index + struct Exemptions { + mapping(address => uint256) exemptIndex; + address[] exemptAddresses; + } + + Exemptions exemptions; + +} diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 505a403ee..ae0c26d21 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -459,7 +459,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater } /** - * @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 { diff --git a/docs/permissions_list.md b/docs/permissions_list.md index b49c95a0e..9e7a213db 100644 --- a/docs/permissions_list.md +++ b/docs/permissions_list.md @@ -143,7 +143,7 @@ allocateTokensMulti() - TransferManager + TransferManager CountTransferManager changeHolderCount() withPerm(ADMIN) @@ -176,19 +176,13 @@ modifyWhitelistMulti() - ManualApprovalTransferManager + ManualApprovalTransferManager addManualApproval() - withPerm(TRANSFER_APPROVAL) - - - addManualBlocking() + withPerm(TRANSFER_APPROVAL) revokeManualApproval() - - revokeManualBlocking() - PercentageTransferManager modifyWhitelist() @@ -205,72 +199,142 @@ changeHolderPercentage() - LockupVolumeRestrictionTM - addLockup() - withPerm(ADMIN) + VolumeRestrictionTM + changeExemptWalletList() + withPerm(ADMIN) - addLockUpMulti() + addIndividualRestriction() - removeLockUp() + addIndividualRestrictionMulti() - modifyLockUp() + addGlobalRestriction() - SingleTradeVolumeRestrictionTM - setAllowPrimaryIssuance() - withPerm(ADMIN) + addDailyGlobalRestriction() + + + removeIndividualRestriction() + + + removeIndividualRestrictionMulti() + + + removeGlobalRestriction() + + + removeDailyGlobalRestriction() + + + modifyIndividualRestriction() + + + modifyIndividualRestrictionMulti() + + + modifyGlobalRestriction() + + + modifyDailyGlobalRestriction() + + + BlacklistTransferManager + addBlacklistType() + withPerm(ADMIN) + + + addBlacklistTypeMulti() - changeTransferLimitToPercentage() + modifyBlacklistType() - changeTransferLimitToTokens() + modifyBlacklistTypeMulti() - changeGlobalLimitInTokens() + deleteBlacklistType() - changeGlobalLimitInPercentage() + deleteBlacklistTypeMulti() - addExemptWallet() + addInvestorToBlacklist() - removeExemptWallet() + addInvestorToBlacklistMulti() - addExemptWalletMulti() + addMultiInvestorToBlacklistMulti() - removeExemptWalletMulti() + addInvestorToNewBlacklist() - setTransferLimitInTokens() + deleteInvestorFromAllBlacklist() - setTransferLimitInPercentage() + deleteInvestorFromAllBlacklistMulti() - removeTransferLimitInPercentage() + deleteInvestorFromBlacklist() - removeTransferLimitInTokens() + deleteMultiInvestorsFromBlacklistMulti() - setTransferLimitInTokensMulti() + Wallet + VestingEscrowWallet + changeTreasuryWallet() + onlyOwner - setTransferLimitInPercentageMulti() + depositTokens() + withPerm(ADMIN) - removeTransferLimitInTokensMulti() + sendToTreasury() - removeTransferLimitInPercentageMulti + pushAvailableTokens() + + addTemplate() + + + removeTemplate() + + + addSchedule() + + + addScheduleFromTemplate() + + + modifySchedule() + + + revokeSchedule() + + + revokeAllSchedules() + + + pushAvailableTokensMulti() + + + addScheduleMulti() + + + addScheduleFromTemplateMulti() + + + revokeSchedulesMulti() + + + modifyScheduleMulti() + diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 9618425c3..47e2ef484 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -28,7 +28,9 @@ const MockOracle = artifacts.require("./MockOracle.sol"); const TokenLib = artifacts.require("./TokenLib.sol"); const SecurityToken = artifacts.require("./tokens/SecurityToken.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); - +const VolumeRestrictionTMFactory = artifacts.require('./VolumeRestrictionTMFactory.sol') +const VolumeRestrictionTMLogic = artifacts.require('./VolumeRestrictionTM.sol'); +const VolumeRestrictionLib = artifacts.require('./VolumeRestrictionLib.sol'); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -176,8 +178,12 @@ 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) @@ -241,6 +247,11 @@ module.exports = function(deployer, network, accounts) { // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(USDTieredSTOLogic, nullAddress, nullAddress, { 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 CappedSTOLogic Contract (Factory used to generate the CappedSTO contract and this // manager attach with the securityToken contract at the time of deployment) @@ -288,6 +299,11 @@ module.exports = function(deployer, network, accounts) { 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, new BN(0), new BN(0), new BN(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) @@ -366,6 +382,11 @@ module.exports = function(deployer, network, accounts) { // 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. @@ -412,6 +433,12 @@ module.exports = function(deployer, network, accounts) { // 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. @@ -460,6 +487,7 @@ module.exports = function(deployer, network, accounts) { .then(() => { console.log("\n"); console.log(` + ----------------------- Polymath Network Smart Contracts: ----------------------- PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistry (Proxy): ${SecurityTokenRegistryProxy.address} @@ -491,6 +519,8 @@ module.exports = function(deployer, network, accounts) { ERC20DividendCheckpointLogic: ${ERC20DividendCheckpointLogic.address} EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + VolumeRestrictionTMFactory: ${VolumeRestrictionTMFactory.address} + VolumeRestrictionTMLogic: ${VolumeRestrictionTMLogic.address} --------------------------------------------------------------------------------- `); console.log("\n"); 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/scripts/test.sh b/scripts/test.sh index 8396cb5a3..039cb43bb 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -96,7 +96,7 @@ if [ "$COVERAGE" = true ]; then 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 + if [ "$CIRCLECI" = true ]; then # using mocha junit reporter for parallelism in CircleCI mkdir test-results mkdir test-results/mocha rm truffle-config.js diff --git a/scripts/tokenInfo-v1.js b/scripts/tokenInfo-v1.js index 490fccfee..ea14a7efe 100644 --- a/scripts/tokenInfo-v1.js +++ b/scripts/tokenInfo-v1.js @@ -1,31 +1,18 @@ const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/")); -var request = require("request-promise"); +var request = require('request-promise') -const securityTokenABI = JSON.parse( - require("fs") - .readFileSync("../CLI/data/SecurityToken1-4-0.json") - .toString() -).abi; -const generalTransferManagerABI = JSON.parse( - require("fs") - .readFileSync("../CLI/data/GeneralTransferManager1-4-0.json") - .toString() -).abi; +const securityTokenABI = JSON.parse(require('fs').readFileSync('../CLI/data/SecurityToken1-4-0.json').toString()).abi; +const generalTransferManagerABI = JSON.parse(require('fs').readFileSync('../CLI/data/GeneralTransferManager1-4-0.json').toString()).abi; async function getTokens() { 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)" - ); + 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); } } @@ -34,22 +21,17 @@ 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())); + 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 getLogsFromEtherscan( - gtmRes.moduleAddress, - web3.utils.hexToNumber("0x5C5C18"), - "latest", - "LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)" - ); + let gtmEvents = await getLogsFromEtherscan(gtmRes.moduleAddress, web3.utils.hexToNumber('0x5C5C18'), 'latest', 'LogModifyWhitelist(address,uint256,address,uint256,uint256,uint256,bool)'); console.log("Count of GeneralTransferManager Events: " + gtmEvents.length); console.log("Modules Attached (TransferManager):"); await getModules(2, token); @@ -59,7 +41,7 @@ async function getInfo(tokenAddress) { await getModules(3, token); console.log("Modules Attached (Checkpoint):"); await getModules(4, token); - console.log(""); + console.log("") console.log(); console.log(); } @@ -83,19 +65,19 @@ async function getModules(type, token) { } async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignature) { - let urlDomain = "api"; + let urlDomain = 'api'; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { - module: "logs", - action: "getLogs", + module: 'logs', + action: 'getLogs', fromBlock: _fromBlock, toBlock: _toBlock, address: _address, topic0: web3.utils.sha3(_eventSignature), - apikey: "THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559" + apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' }, - method: "GET", + method: 'GET', json: true }; let data = await request(options); @@ -103,20 +85,20 @@ async function getLogsFromEtherscan(_address, _fromBlock, _toBlock, _eventSignat } async function getABIfromEtherscan(_address) { - let urlDomain = "api"; + let urlDomain = 'api'; const options = { url: `https://${urlDomain}.etherscan.io/api`, qs: { - module: "contract", - action: "getabi", + module: 'contract', + action: 'getabi', address: _address, - apikey: "THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559" + apikey: 'THM9IUVC2DJJ6J5MTICDE6H1HGQK14X559' }, - method: "GET", + method: 'GET', json: true }; let data = await request(options); return JSON.parse(data.result); } -getTokens(); +getTokens(); \ No newline at end of file diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 94d0d4368..d98271c7e 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -128,13 +128,12 @@ contract("CappedSTO", async (accounts) => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied, + I_STRProxied, I_STRGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, new BN(0)); - // STEP 6: Deploy the CappedSTOFactory [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(account_polymath, I_MRProxied, cappedSTOSetupCost); @@ -168,7 +167,7 @@ contract("CappedSTO", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -330,7 +329,7 @@ contract("CappedSTO", async (accounts) => { it("Should Buy the tokens", async () => { balanceOfReceiver = new BN(await web3.eth.getBalance(account_fundsReceiver)); - + await I_CappedSTO_Array_ETH[0].buyTokens(account_investor1, { from: account_investor1, value: web3.utils.toWei("1", "ether") @@ -616,14 +615,14 @@ contract("CappedSTO", async (accounts) => { 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 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[2].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); I_SecurityToken_POLY = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + const log = (await I_SecurityToken_POLY.getPastEvents('ModuleAdded', {filter: {from: blockNo}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -837,7 +836,7 @@ contract("CappedSTO", async (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 () => { diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 18594249d..d6de7c581 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -136,7 +136,7 @@ contract("CountTransferManager", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); @@ -360,7 +360,7 @@ contract("CountTransferManager", async (accounts) => { 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 tx2 = await I_STRProxied.generateSecurityToken(name, symbol2, tokenDetails, false, { from: token_owner }); I_SecurityToken2 = await SecurityToken.at(tx2.logs[2].args._securityTokenAddress); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 49472fc7a..f17bd200a 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", async (accounts) => { let account_polymath; let account_issuer; let token_owner; + let wallet; let account_investor1; let account_investor2; let account_investor3; @@ -75,6 +77,8 @@ contract("ERC20DividendCheckpoint", async (accounts) => { let currentTime; + const DividendParameters = ["address"]; + before(async () => { currentTime = new BN(await latestTime()); account_polymath = accounts[0]; @@ -88,6 +92,7 @@ contract("ERC20DividendCheckpoint", async (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); @@ -141,7 +146,7 @@ contract("ERC20DividendCheckpoint", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -161,8 +166,9 @@ contract("ERC20DividendCheckpoint", async (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, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -172,7 +178,8 @@ contract("ERC20DividendCheckpoint", async (accounts) => { let snapId = await takeSnapshot(); await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); - const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); @@ -186,7 +193,8 @@ contract("ERC20DividendCheckpoint", async (accounts) => { }); it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, bytesDividend, new BN(0), new BN(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, ""), @@ -334,6 +342,12 @@ contract("ERC20DividendCheckpoint", async (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].toString(), new BN(web3.utils.toWei("1.5", "ether")).toString(), "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 () => { @@ -416,6 +430,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { dividendName, { from: token_owner } ); + 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"); }); @@ -462,7 +477,9 @@ contract("ERC20DividendCheckpoint", async (accounts) => { limit = limit.toNumber() + 42; let addresses = []; addresses.push(account_temp); - while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); + let tempAdd = '0x0000000000000000000000000000000000000000'; + while (--limit > 42) addresses.push(web3.utils.toChecksumAddress(tempAdd.substring(0, 42 - limit.toString().length) + limit)); + //'0x00000000000000000000000000000000000000' + limit)); await I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner }); let excluded = await I_ERC20DividendCheckpoint.getDefaultExcluded(); assert.equal(excluded[0], account_temp); @@ -493,7 +510,11 @@ contract("ERC20DividendCheckpoint", async (accounts) => { limit = limit.toNumber() + 42; let addresses = []; addresses.push(account_temp); - while (limit-- > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); + let tempAdd = '0x0000000000000000000000000000000000000000'; + while (limit-- > 42) addresses.push(web3.utils.toChecksumAddress(tempAdd.substring(0, 42 - limit.toString().length) + limit)); + + // while (limit-- > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); + console.log(addresses.length); await catchRevert(I_ERC20DividendCheckpoint.setDefaultExcluded(addresses, { from: token_owner })); }); @@ -510,7 +531,9 @@ contract("ERC20DividendCheckpoint", async (accounts) => { dividendName, { from: token_owner } ); + 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((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 () => { @@ -529,6 +552,16 @@ contract("ERC20DividendCheckpoint", async (accounts) => { assert.equal(investor1BalanceAfter1.sub(investor1Balance).toNumber(), 0); assert.equal(investor2BalanceAfter1.sub(investor2Balance).toNumber(), 0); assert.equal(investor3BalanceAfter1.sub(investor3Balance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); + 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[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 () => { @@ -667,7 +700,9 @@ contract("ERC20DividendCheckpoint", async (accounts) => { let addresses = []; addresses.push(account_temp); addresses.push(token_owner); - while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); + let tempAdd = '0x0000000000000000000000000000000000000000'; + while (--limit > 42) addresses.push(web3.utils.toChecksumAddress(tempAdd.substring(0, 42 - limit.toString().length) + limit)); + // while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); await catchRevert( I_ERC20DividendCheckpoint.createDividendWithCheckpointAndExclusions( maturity, @@ -697,7 +732,7 @@ contract("ERC20DividendCheckpoint", async (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 () => { @@ -825,10 +860,80 @@ contract("ERC20DividendCheckpoint", async (accounts) => { }); it("Issuer reclaims withholding tax", async () => { - let issuerBalance = new BN(await I_PolyToken.balanceOf(token_owner)); - await I_ERC20DividendCheckpoint.withdrawWithholding(3, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BN(await I_PolyToken.balanceOf(token_owner)); + let info = await I_ERC20DividendCheckpoint.getDividendProgress.call(3); + + 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].toString()); + console.log(info[3][1].toString()); + console.log(info[3][2].toString()); + console.log(info[3][3].toString()); + + console.log("Claimed:"); + console.log(info[4][0].toString()); + console.log(info[4][1].toString()); + console.log(info[4][2].toString()); + console.log(info[4][3].toString()); + + console.log("Balance:"); + console.log(info[5][0].toString()); + console.log(info[5][1].toString()); + console.log(info[5][2].toString()); + console.log(info[5][3].toString()); + + 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].toString(), 0, "withheld match"); + assert.equal(info[3][1].toString(), new BN(web3.utils.toWei("0.2", "ether")).toString(), "withheld match"); + assert.equal(info[3][2].toString(), new BN(web3.utils.toWei("0.2", "ether")).toString(), "withheld match"); + assert.equal(info[3][3].toString(), 0, "withheld match"); + + assert.equal(info[4][0].toString(), 0, "excluded"); + assert.equal(info[4][1].toString(), new BN(web3.utils.toWei("1.8", "ether")).toString(), "claim match"); + assert.equal(info[4][2].toString(), new BN(web3.utils.toWei("0.8", "ether")).toString(), "claim match"); + assert.equal(info[4][3].toString(), new BN(web3.utils.toWei("7", "ether")).toString(), "claim match"); + + assert.equal(info[5][0].toString(), (await I_SecurityToken.balanceOfAt(account_investor1, new BN(4))).toString(), "balance match"); + assert.equal(info[5][1].toString(), (await I_SecurityToken.balanceOfAt(account_investor2, new BN(4))).toString(), "balance match"); + assert.equal(info[5][2].toString(), (await I_SecurityToken.balanceOfAt(account_temp, new BN(4))).toString(), "balance match"); + assert.equal(info[5][3].toString(), (await I_SecurityToken.balanceOfAt(account_investor3, new BN(4))).toString(), "balance match"); + + + let issuerBalance = new BN(await I_PolyToken.balanceOf(wallet)); + await I_ERC20DividendCheckpoint.withdrawWithholding(new BN(3), { from: token_owner, gasPrice: 0 }); + let issuerBalanceAfter = new BN(await I_PolyToken.balanceOf(wallet)); assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0.4", "ether")).toString()); + + }); + + 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 () => { @@ -845,9 +950,9 @@ contract("ERC20DividendCheckpoint", async (accounts) => { }); it("Issuer is able to reclaim dividend after expiry", async () => { - let tokenOwnerBalance = new BN(await I_PolyToken.balanceOf(token_owner)); + let tokenOwnerBalance = new BN(await I_PolyToken.balanceOf(wallet)); await I_ERC20DividendCheckpoint.reclaimDividend(3, { from: token_owner, gasPrice: 0 }); - let tokenOwnerAfter = new BN(await I_PolyToken.balanceOf(token_owner)); + let tokenOwnerAfter = new BN(await I_PolyToken.balanceOf(wallet)); assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); @@ -869,11 +974,6 @@ contract("ERC20DividendCheckpoint", async (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); @@ -1036,13 +1136,27 @@ contract("ERC20DividendCheckpoint", async (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].toString(), (await I_SecurityToken.balanceOfAt.call(account_investor1, checkpointID)).toString(), "balance match"); + assert.equal(info[1][1].toString(), (await I_SecurityToken.balanceOfAt.call(account_investor2, checkpointID)).toString(), "balance match"); + assert.equal(info[1][2].toString(), (await I_SecurityToken.balanceOfAt.call(account_temp, checkpointID)).toString(), "balance match"); + assert.equal(info[1][3].toString(), (await I_SecurityToken.balanceOfAt.call(account_investor3, checkpointID)).toString(), "balance match"); + assert.equal(info[2][0].toNumber(), 0, "withholding match"); + assert.equal(info[2][1].toString(), new BN((10 * 10 ** 16).toString()).toString(), "withholding match"); + assert.equal(info[2][2].toString(), new BN((20 * 10 ** 16).toString()).toString(), "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 () => { - let maturity = await latestTime() + duration.days(1); - let expiry = await latestTime() + duration.days(10); - let exclusions = [one_address]; + let maturity = (await latestTime()) + duration.days(1); + let expiry = (await latestTime()) + duration.days(10); + let exclusions = [account_temp]; let tx = await I_ERC20DividendCheckpoint.createDividendWithExclusions( maturity, expiry, @@ -1053,6 +1167,10 @@ contract("ERC20DividendCheckpoint", async (accounts) => { { from: account_manager } ); 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.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"); }); it("should allow manager with permission to create dividend with checkpoint and exclusion", async () => { diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 8d9582283..dae87c572 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", async (accounts) => { let account_polymath; let account_issuer; let token_owner; + let wallet; let account_investor1; let account_investor2; let account_investor3; @@ -66,6 +68,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { const transferManagerKey = 2; const stoKey = 3; const checkpointKey = 4; + const DividendParameters = ["address"]; // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); @@ -85,6 +88,7 @@ contract("EtherDividendCheckpoint", async (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); @@ -135,7 +139,7 @@ contract("EtherDividendCheckpoint", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -157,8 +161,9 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); await catchRevert( - I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }) ); @@ -167,7 +172,8 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); - const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "0x0", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); @@ -181,7 +187,8 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); + let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); + const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, bytesDividend, new BN(0), new BN(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, ""), @@ -344,9 +351,9 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Issuer reclaims withholding tax", async () => { - let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.withdrawWithholding(0, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(wallet)); assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0.2", "ether")).toString()); }); @@ -492,9 +499,9 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Issuer withdraws new withholding tax", async () => { - let issuerBalance = new BN(await web3.eth.getBalance(token_owner)); + let issuerBalance = new BN(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.withdrawWithholding(2, { from: token_owner, gasPrice: 0 }); - let issuerBalanceAfter = new BN(await web3.eth.getBalance(token_owner)); + let issuerBalanceAfter = new BN(await web3.eth.getBalance(wallet)); assert.equal(issuerBalanceAfter.sub(issuerBalance).toString(), new BN(web3.utils.toWei("0.6", "ether")).toString()); }); @@ -556,7 +563,9 @@ contract("EtherDividendCheckpoint", async (accounts) => { let addresses = []; addresses.push(account_temp); addresses.push(token_owner); - while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); + let tempAdd = '0x0000000000000000000000000000000000000000'; + while (--limit > 42) addresses.push(web3.utils.toChecksumAddress(tempAdd.substring(0, 42 - limit.toString().length) + limit)); + // while (--limit > 42) addresses.push(web3.utils.toChecksumAddress('0x00000000000000000000000000000000000000' + limit)); await catchRevert( I_EtherDividendCheckpoint.createDividendWithCheckpointAndExclusions(maturity, expiry, 4, addresses, dividendName, { from: token_owner, @@ -700,9 +709,9 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Issuer is able to reclaim dividend after expiry", async () => { - let tokenOwnerBalance = new BN(await web3.eth.getBalance(token_owner)); + let tokenOwnerBalance = new BN(await web3.eth.getBalance(wallet)); await I_EtherDividendCheckpoint.reclaimDividend(3, { from: token_owner, gasPrice: 0 }); - let tokenOwnerAfter = new BN(await web3.eth.getBalance(token_owner)); + let tokenOwnerAfter = new BN(await web3.eth.getBalance(wallet)); assert.equal(tokenOwnerAfter.sub(tokenOwnerBalance).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); @@ -782,11 +791,6 @@ contract("EtherDividendCheckpoint", async (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); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 4876765fc..83f297ae7 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -160,7 +160,7 @@ contract("GeneralTransferManager", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -941,3 +941,6 @@ function range1(i) { function rangeB(i) { return i ? rangeB(i - 1).concat(0) : []; } + +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 4c9f6090c..130f0ff62 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -18,6 +18,7 @@ const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApproval const TrackedRedemptionFactory = artifacts.require("./TrackedRedemptionFactory.sol"); const PercentageTransferManagerFactory = artifacts.require("./PercentageTransferManagerFactory.sol"); const PercentageTransferManager = artifacts.require("./PercentageTransferManager.sol"); +const BlacklistTransferManagerFactory = artifacts.require("./BlacklistTransferManagerFactory.sol"); const ScheduledCheckpointFactory = artifacts.require('./ScheduledCheckpointFactory.sol'); const USDTieredSTOFactory = artifacts.require("./USDTieredSTOFactory.sol"); const USDTieredSTO = artifacts.require("./USDTieredSTO"); @@ -29,7 +30,7 @@ const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.s const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const CountTransferManager = artifacts.require("./CountTransferManager.sol"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); -const VolumeRestrictionTransferManagerFactory = artifacts.require("./LockupVolumeRestrictionTMFactory"); +const LockUpTransferManagerFactory = artifacts.require("./LockUpTransferManagerFactory"); const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PreSaleSTO = artifacts.require("./PreSaleSTO.sol"); const PolyToken = artifacts.require("./PolyToken.sol"); @@ -39,6 +40,10 @@ const DummySTO = artifacts.require("./DummySTO.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const STRGetter = artifacts.require("./STRGetter.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); +const VolumeRestrictionTMFactory = artifacts.require("./VolumeRestrictionTMFactory.sol"); +const VolumeRestrictionTM = artifacts.require("./VolumeRestrictionTM.sol"); +const VestingEscrowWalletFactory = artifacts.require("./VestingEscrowWalletFactory.sol"); +const VestingEscrowWallet = artifacts.require("./VestingEscrowWallet.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -63,10 +68,13 @@ let I_CountTransferManagerFactory; let I_ERC20DividendCheckpointLogic; let I_ERC20DividendCheckpointFactory; let I_GeneralPermissionManagerLogic; +let I_VolumeRestrictionTMFactory; let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerLogic; let I_GeneralTransferManagerFactory; +let I_VestingEscrowWalletFactory; let I_GeneralTransferManager; +let I_VolumeRestrictionTMLogic; let I_ModuleRegistryProxy; let I_PreSaleSTOLogic; let I_PreSaleSTOFactory; @@ -83,6 +91,8 @@ let I_STFactory; let I_USDTieredSTOLogic; let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; +let I_BlacklistTransferManagerFactory; +let I_VestingEscrowWalletLogic; let I_STRProxied; let I_MRProxied; let I_STRGetter; @@ -132,7 +142,7 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { return Promise.all(tempArray); } -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 }); @@ -265,6 +275,22 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, set return Promise.all(new Array(I_GeneralTransferManagerFactory)); } +export async function deployVRTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_VolumeRestrictionTMLogic = await VolumeRestrictionTM.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + + I_VolumeRestrictionTMFactory = await VolumeRestrictionTMFactory.new(setupCost, new BN(0), new BN(0), I_VolumeRestrictionTMLogic.address, { 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, setupCost) { I_CountTransferManagerLogic = await CountTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_CountTransferManagerLogic.address, { from: accountPolymath }); @@ -305,14 +331,27 @@ export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInst return Promise.all(new Array(I_PercentageTransferManagerFactory)); } +export async function deployBlacklistTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { + + I_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(setupCost, new BN(0), new BN(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 deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_VolumeRestrictionTransferManagerFactory = await VolumeRestrictionTransferManagerFactory.new(setupCost, new BN(0), new BN(0), { + I_VolumeRestrictionTransferManagerFactory = await LockUpTransferManagerFactory.new(setupCost, new BN(0), new BN(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); @@ -465,6 +504,20 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan return Promise.all(new Array(I_TrackedRedemptionFactory)); } +export async function deployVestingEscrowWalletAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { + I_VestingEscrowWalletLogic = await VestingEscrowWallet.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); + I_VestingEscrowWalletFactory = await VestingEscrowWalletFactory.new(setupCost, new BN(0), new BN(0), I_VestingEscrowWalletLogic.address, { 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, setupCost) { I_MockBurnFactory = await MockBurnFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); 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/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 7ac1bd4cf..26580b093 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -3,12 +3,7 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from "./hel import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { - setUpPolymathNetwork, - deployManualApprovalTMAndVerifyed, - deployGPMAndVerifyed, - deployCountTMAndVerifyed -} from "./helpers/createInstances"; +import { setUpPolymathNetwork, deployManualApprovalTMAndVerifyed, deployGPMAndVerifyed, deployCountTMAndVerifyed } from "./helpers/createInstances"; const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); @@ -20,7 +15,7 @@ const Web3 = require("web3"); let BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -contract("ManualApprovalTransferManager", async (accounts) => { +contract("ManualApprovalTransferManager", accounts => { // Accounts Variable declaration let account_polymath; let account_issuer; @@ -31,6 +26,11 @@ contract("ManualApprovalTransferManager", async (accounts) => { 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 @@ -55,7 +55,6 @@ contract("ManualApprovalTransferManager", async (accounts) => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; - let I_STRGetter; // SecurityToken Details const name = "Team"; @@ -69,17 +68,17 @@ contract("ManualApprovalTransferManager", async (accounts) => { const transferManagerKey = 2; const stoKey = 3; + let expiryTimeMA; + let approvalTime; + // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = web3.utils.toWei("250"); const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; - let currentTime; - const address_zero = "0x0000000000000000000000000000000000000000"; - const one_address = "0x0000000000000000000000000000000000000001"; - before(async () => { currentTime = new BN(await latestTime()); + // Accounts setup account_polymath = accounts[0]; account_issuer = accounts[1]; @@ -105,8 +104,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied, - I_STRGetter + I_STRProxied ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -114,11 +112,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { // STEP 3: Deploy the ManualApprovalTransferManagerFactory [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, 0); // STEP 4: Deploy the Paid ManualApprovalTransferManagerFactory - [P_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed( - account_polymath, - I_MRProxied, - new BN(web3.utils.toWei("500", "ether")) - ); + [P_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); // STEP 5: Deploy the CountTransferManagerFactory [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); @@ -151,7 +145,7 @@ contract("ManualApprovalTransferManager", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -162,7 +156,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(log.args._types[0].toString(), 2); assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); }); @@ -180,7 +174,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { account_investor1, currentTime, currentTime, - currentTime.add(new BN(duration.days(10))), + currentTime.add(new BN(duration.days(30))), true, { from: account_issuer, @@ -196,11 +190,11 @@ contract("ManualApprovalTransferManager", async (accounts) => { // Jump time await increaseTime(5000); - + currentTime = new BN(await latestTime()); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(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)).toString(), new BN(web3.utils.toWei("4", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), web3.utils.toWei("30", "ether")); }); it("Should Buy some more tokens", async () => { @@ -210,7 +204,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { account_investor2, currentTime, currentTime, - currentTime.add(new BN(duration.days(10))), + currentTime.add(new BN(duration.days(30))), true, { from: account_issuer, @@ -225,15 +219,15 @@ contract("ManualApprovalTransferManager", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), web3.utils.toWei("10", "ether")); }); it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x0", web3.utils.toWei("500", "ether"), 0, { from: token_owner }) ); @@ -241,15 +235,15 @@ contract("ManualApprovalTransferManager", async (accounts) => { 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, new BN(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_ManualApprovalTransferManagerFactory.address, - "0x", - new BN(web3.utils.toWei("500", "ether")), - new BN(0), + "0x0", + 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(tx.logs[3].args._types[0].toString(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), "ManualApprovalTransferManager", @@ -260,8 +254,8 @@ contract("ManualApprovalTransferManager", async (accounts) => { }); it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); + const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "0x0", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toString(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); assert.equal( web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", @@ -275,7 +269,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { I_ManualApprovalTransferManager.verifyTransfer( account_investor4, account_investor4, - new BN(web3.utils.toWei("2", "ether")), + web3.utils.toWei("2", "ether"), "0x0", true, { from: token_owner } @@ -287,7 +281,7 @@ contract("ManualApprovalTransferManager", async (accounts) => { await I_ManualApprovalTransferManager.verifyTransfer( account_investor4, account_investor4, - new BN(web3.utils.toWei("2", "ether")), + web3.utils.toWei("2", "ether"), "0x0", false, { from: token_owner } @@ -313,31 +307,32 @@ contract("ManualApprovalTransferManager", async (accounts) => { "Failed in adding the investor in whitelist" ); // Pause at the transferManager level - await I_ManualApprovalTransferManager.pause({ from: token_owner }); + await I_ManualApprovalTransferManager.pause({from: token_owner}); // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, new BN(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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), web3.utils.toWei("10", "ether")); // Unpause at the transferManager level - await I_ManualApprovalTransferManager.unpause({ from: token_owner }); + await I_ManualApprovalTransferManager.unpause({from: token_owner}); }); 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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei("1", "ether"), { from: account_investor2 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("5", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), web3.utils.toWei("31", "ether")); }); it("Should fail to add a manual approval because invalid _to address", async () => { await catchRevert( I_ManualApprovalTransferManager.addManualApproval( account_investor1, - address_zero, - new BN(web3.utils.toWei("2", "ether")), + "0x0000000000000000000000000000000000000000", + web3.utils.toWei("2", "ether"), currentTime.add(new BN(duration.days(1))), + web3.utils.fromAscii("DESCRIPTION"), { from: token_owner } ) ); @@ -348,159 +343,434 @@ contract("ManualApprovalTransferManager", async (accounts) => { I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - new BN(web3.utils.toWei("2", "ether")), + web3.utils.toWei("2", "ether"), 99999, + web3.utils.fromAscii("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 () => { + approvalTime = currentTime.add(new BN(duration.days(1))); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - new BN(web3.utils.toWei("2", "ether")), - currentTime.add(new BN(duration.days(1))), - { from: token_owner } + web3.utils.toWei("3", "ether"), + approvalTime, + web3.utils.fromAscii("DESCRIPTION"), + { + from: token_owner + } ); + assert.equal((await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toString(), 1); }); - it("Add a manual approval for a 5th investor from issuance", async () => { - await I_ManualApprovalTransferManager.addManualApproval( - address_zero, - account_investor5, - new BN(web3.utils.toWei("2", "ether")), - currentTime.add(new BN(duration.days(1))), - { from: token_owner } - ); - }); + it("Should return all approvals correctly", async () => { + + console.log("current approval length is " + (await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toString()); - it("Should fail to add a manual approval because allowance is laready exists", async () => { + 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].toString(), approvalTime); + 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( account_investor1, account_investor4, - new BN(web3.utils.toWei("2", "ether")), - currentTime.add(new BN(duration.days(5))), - { from: token_owner } + web3.utils.toWei("5", "ether"), + currentTime.add(new BN(duration.days(1))), + web3.utils.fromAscii("DESCRIPTION"), + { + from: token_owner + } ) ); + }) + + it("Check verifyTransfer without actually transferring", async () => { + let verified = await I_SecurityToken.verifyTransfer.call( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + "0x0" + ); + console.log(JSON.stringify(verified)); + assert.equal(verified, true); + + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("4", "ether"), "0x0"); + assert.equal(verified, false); + + verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("1", "ether"), "0x0"); + assert.equal(verified, true); }); - it("Should fail to revoke manual approval because invalid _to address", async () => { - await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, address_zero, { 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}) + ); + }) + + 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 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 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.sub(oldBal4)).div(new BN(10).pow(new BN(18))).toString(), 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.sub(oldBal4)).div(new BN(10).pow(new BN(18))).toString(), 1); + + + 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() => { + await increaseTime(duration.days(1)); + currentTime = new BN(await latestTime()); + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei("1"), {from: account_investor1}) + ); + }); + + it("Should fail to modify the manual approval when the approval get expired", async() => { + await catchRevert( + I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + currentTime.add(new BN(duration.days(2))), + web3.utils.toWei("5"), + web3.utils.fromAscii("New Description"), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should attach the manual approval for the investor4 again", async() => { + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4))[0].length, 0); + currentTime = new BN(await latestTime()); await I_ManualApprovalTransferManager.addManualApproval( account_investor1, account_investor4, - new BN(web3.utils.toWei("2", "ether")), + web3.utils.toWei("2", "ether"), currentTime.add(new BN(duration.days(1))), - { from: token_owner } + web3.utils.fromAscii("DESCRIPTION"), + { + from: token_owner + } ); + assert.equal((await I_ManualApprovalTransferManager.getTotalApprovalsLength.call()).toString(), 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("Should modify the manual approval expiry time for 4th investor", async () => { + currentTime = new BN(await latestTime()); + expiryTimeMA = currentTime.add(new BN(duration.days(3))); + let tx = await I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("5"), + web3.utils.fromAscii("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].toString(), 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).toString(), expiryTimeMA); + assert.equal((tx.logs[0].args._allowance).toString(), web3.utils.toWei("2")); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._description), "New Description"); }); - it("Use 50% of manual approval for transfer", async () => { - await I_SecurityToken.transfer(account_investor4, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + it("Should transact after two days", async() => { + await increaseTime(2); + currentTime = new BN(await latestTime()); + 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.sub(oldBal4)).div(new BN(10).pow(new BN(18))).toString(), 1); }); - it("Approval fails with wrong from to address", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor5, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); + it("Should modify the allowance of the manual approval (increase)", async() => { + currentTime = new BN(await latestTime()); + await I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("4"), + web3.utils.fromAscii("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].toString(), web3.utils.toWei("5")); + assert.equal(data[3].toString(), expiryTimeMA); + assert.equal(web3.utils.toUtf8(data[4]), "New Description"); }); - it("Use 100% of issuance approval", async () => { - await I_SecurityToken.mint(account_investor5, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor5)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + it("Should transact according to new allowance", async() => { + currentTime = new BN(await latestTime()); + 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.sub(oldBal4)).div(new BN(10).pow(new BN(18))).toString(), 3); }); - it("Check verifyTransfer without actually transferring", async () => { - let verified = await I_SecurityToken.verifyTransfer.call( + it("Should decrease the allowance", async() => { + currentTime = new BN(await latestTime()); + await I_ManualApprovalTransferManager.modifyManualApproval( account_investor1, account_investor4, - new BN(web3.utils.toWei("1", "ether")), - "0x0" + expiryTimeMA, + web3.utils.toWei("1"), + web3.utils.fromAscii("New Description"), + 0, + { + from: token_owner + } ); - assert.equal(verified, true); - - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, new BN(web3.utils.toWei("2", "ether")), "0x0"); - assert.equal(verified, false); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, new BN(web3.utils.toWei("1", "ether")), "0x0"); - assert.equal(verified, true); + let data = await I_ManualApprovalTransferManager.approvals.call(0); + assert.equal(data[0], account_investor1); + assert.equal(data[1], account_investor4); + assert.equal(data[2].toString(), web3.utils.toWei("1")); + assert.equal(data[3].toString(), expiryTimeMA); + assert.equal(web3.utils.toUtf8(data[4]), "New Description"); }); - it("Use remaining 50% of manual approval for transfer", async () => { - await I_SecurityToken.transfer(account_investor4, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor4)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + 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("Check further transfers fail", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor4, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); - - //Check that other transfers are still valid - await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + it("Should successfully transfer the tokens within the allowance limit", async() => { + currentTime = new BN(await latestTime()); + 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.sub(oldBal4)).div(new BN(10).pow(new BN(18))).toString(), 1); }); - it("Should fail to add a manual block because invalid _to address", async () => { + it("Should fail to modify because allowance is zero", async() => { await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, address_zero, currentTime.add(new BN(duration.days(1))), { - from: token_owner - }) + I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("5"), + web3.utils.fromAscii("New Description"), + 0, + { + from: token_owner + } + ) ); }); - it("Should fail to add a manual block because invalid expiry time", async () => { + it("Should fail to revoke the manual Approval -- bad owner", async() => { await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, 99999, { from: token_owner }) + I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: account_investor5}) ); - }); + }) - it("Add a manual block for a 2nd investor", async () => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(duration.days(1))), { - from: token_owner - }); + 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))[0].length, 0); + assert.equal((await I_ManualApprovalTransferManager.getActiveApprovalsToUser.call(account_investor4))[0].length, 0); }); - it("Should fail to add a manual block because blocking already exist", async () => { + it("Should fail to revoke the same manual approval again", async() => { await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(duration.days(5))), { - from: token_owner - }) + I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}) ); }); - it("Check manual block causes failure", async () => { - await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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")], + [currentTime.add(new BN(duration.days(1))),currentTime.add(new BN(duration.days(1)))], + [web3.utils.fromAscii("DESCRIPTION_1"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.days(1))),currentTime.add(new BN(duration.days(1)))], + [web3.utils.fromAscii("DESCRIPTION_1"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.days(1)))], + [web3.utils.fromAscii("DESCRIPTION_1"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.days(1))),currentTime.add(new BN(duration.days(1)))], + [web3.utils.fromAscii("DESCRIPTION_1"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.days(1))),currentTime.add(new BN(duration.days(1)))], + [web3.utils.fromAscii("DESCRIPTION_1")], + { + from: token_owner + } + ) + ) }); - it("Should fail to revoke manual block because invalid _to address", async () => { - await catchRevert(I_ManualApprovalTransferManager.revokeManualBlocking(account_investor1, address_zero, { from: token_owner })); - }); + it("Add multiple manual approvals", async () => { + let time = currentTime.add(new BN(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,currentTime.add(new BN(duration.days(1)))], + [web3.utils.fromAscii("DESCRIPTION_1"), web3.utils.fromAscii("DESCRIPTION_2")], + { + 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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 2); + 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].toString(), time); + assert.equal(approvalDetail[1].toString(), web3.utils.toWei("2", "ether")); + assert.equal(web3.utils.toUtf8(approvalDetail[2]), "DESCRIPTION_1"); }); - it("Check manual block ignored after expiry", async () => { - await I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, currentTime.add(new BN(duration.days(1))), { - from: token_owner - }); + 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 + } + ) + ); + }) - await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); - await increaseTime(1 + 24 * 60 * 60); - await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + 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( + "0x0000000000000000000000000000000000000000", + account_investor5, + web3.utils.toWei("2", "ether"), + currentTime.add(new BN(duration.days(1))), + web3.utils.fromAscii("DESCRIPTION"), + { + from: token_owner + } + ); }); it("Should successfully attach the CountTransferManager with the security token (count of 1)", async () => { @@ -518,8 +788,8 @@ contract("ManualApprovalTransferManager", async (accounts) => { [1] ); - const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, new BN(0), new BN(0), { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toString(), 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 = await CountTransferManager.at(tx.logs[2].args._module); @@ -543,16 +813,16 @@ contract("ManualApprovalTransferManager", async (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"); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 1504d86b6..efba2e2f2 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -192,33 +192,33 @@ contract("ModuleRegistry", async (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, @@ -481,10 +481,10 @@ contract("ModuleRegistry", async (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); }); @@ -507,10 +507,10 @@ contract("ModuleRegistry", async (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 () => { @@ -548,7 +548,7 @@ contract("ModuleRegistry", async (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); }); @@ -558,7 +558,7 @@ contract("ModuleRegistry", async (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/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index f98e2c41f..b27f34427 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -132,7 +132,6 @@ contract("PercentageTransferManager", async (accounts) => { I_MRProxied, new BN(web3.utils.toWei("500", "ether")) ); - // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- @@ -162,7 +161,7 @@ contract("PercentageTransferManager", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 05955cb71..bc7a2731d 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -127,7 +127,7 @@ contract("SecurityTokenRegistry", async (accounts) => { console.log(I_SecurityTokenRegistry.address); I_SecurityTokenRegistry = await SecurityTokenRegistry.new({ from: account_polymath }); console.log(I_SecurityTokenRegistry.address); - + assert.notEqual( I_SecurityTokenRegistry.address.valueOf(), address_zero, @@ -227,7 +227,7 @@ contract("SecurityTokenRegistry", async (accounts) => { "tx-> revert because tickerRegFee is 0" ); }); - + it("Should successfully update the implementation address -- fail because owner address is 0x", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, @@ -274,28 +274,28 @@ contract("SecurityTokenRegistry", async (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.toString(), initRegFee.toString(), "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.toString(), tickerRegFee.toString(), "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 getterContract = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("STRGetter")); + let getterContract = await I_STRProxied.getAddressValue.call(web3.utils.soliditySha3("STRGetter")); assert.equal(getterContract, I_STRGetter.address, "Should be the address of the getter contract"); - 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"); }); @@ -417,7 +417,7 @@ contract("SecurityTokenRegistry", async (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" ); @@ -501,7 +501,7 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -596,7 +596,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should generate the new security token with version 2", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - + let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -628,7 +628,7 @@ contract("SecurityTokenRegistry", async (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 () => { @@ -640,7 +640,7 @@ contract("SecurityTokenRegistry", async (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"); }); }); @@ -895,7 +895,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should able to change the STLaunchFee", async () => { let tx = await I_STRProxied.changeSecurityLaunchFee(new BN(web3.utils.toWei("500")), { from: account_polymath }); assert.equal(tx.logs[0].args._newFee.toString(), new BN(web3.utils.toWei("500")).toString()); - let stLaunchFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("stLaunchFee")); + let stLaunchFee = await I_STRProxied.getUintValue(web3.utils.soliditySha3("stLaunchFee")); assert.equal(stLaunchFee.toString(), new BN(web3.utils.toWei("500")).toString()); }); }); @@ -918,7 +918,7 @@ contract("SecurityTokenRegistry", async (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)); }); }); @@ -941,7 +941,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should able to change the TickerRegFee", async () => { let tx = await I_STRProxied.changeTickerRegistrationFee(new BN(web3.utils.toWei("400")), { from: account_polymath }); assert.equal(tx.logs[0].args._newFee.toString(), new BN(web3.utils.toWei("400")).toString()); - let tickerRegFee = await I_STRProxied.getUintValues(web3.utils.soliditySha3("tickerRegFee")); + let tickerRegFee = await I_STRProxied.getUintValue(web3.utils.soliditySha3("tickerRegFee")); assert.equal(tickerRegFee.toString(), new BN(web3.utils.toWei("400")).toString()); }); @@ -978,6 +978,29 @@ contract("SecurityTokenRegistry", async (accounts) => { }); }); + describe("Test case for the update poly token", async () => { + it("Should change the polytoken address -- failed because of bad owner", async () => { + catchRevert( + I_STRProxied.updatePolyTokenAddress(dummy_token, { from: account_temp }), + "tx revert -> failed because of bad owner" + ); + }); + + it("Should change the polytoken address -- failed because of 0x address", async () => { + catchRevert( + I_STRProxied.updatePolyTokenAddress(address_zero, { from: account_polymath }), + "tx revert -> failed because 0x address" + ); + }); + + 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.getAddressValue.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_Getter.getSecurityTokenAddress.call(symbol); @@ -1117,7 +1140,7 @@ contract("SecurityTokenRegistry", async (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); }); @@ -1127,7 +1150,7 @@ contract("SecurityTokenRegistry", async (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/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1ee447b7f..4661fb043 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -161,8 +161,8 @@ contract("USDTieredSTO", async (accounts) => { name: "_reserveWallet" }, { - type: "address", - name: "_usdToken" + type: "address[]", + name: "_usdTokens" } ] }; @@ -280,7 +280,7 @@ contract("USDTieredSTO", async (accounts) => { 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 tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); assert.equal(tx.logs[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); @@ -304,7 +304,7 @@ contract("USDTieredSTO", async (accounts) => { let stoId = 0; // No discount _startTime.push(new BN(currentTime).add(new BN(duration.days(2)))); - _endTime.push(new BN(_startTime[stoId]).add(new BN(currentTime).add(new BN(duration.days(100))))); + _endTime.push(_startTime[stoId].add(new BN(duration.days(100)))); _ratePerTier.push([new BN(10).mul(e16), new BN(15).mul(e16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] _ratePerTierDiscountPoly.push([new BN(10).mul(e16), new BN(15).mul(e16)]); // [ 0.10 USD/Token, 0.15 USD/Token ] _tokensPerTierTotal.push([new BN(100000000).mul(new BN(e18)), new BN(200000000).mul(new BN(e18))]); // [ 100m Token, 200m Token ] @@ -314,7 +314,7 @@ contract("USDTieredSTO", async (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], @@ -378,7 +378,7 @@ contract("USDTieredSTO", async (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].getUsdTokens())[0], _usdToken[stoId][0], "Incorrect _usdToken in config"); assert.equal( await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, @@ -503,7 +503,7 @@ contract("USDTieredSTO", async (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], @@ -567,7 +567,7 @@ contract("USDTieredSTO", async (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].getUsdTokens())[0], _usdToken[stoId][0], "Incorrect _usdToken in config"); assert.equal( await I_USDTieredSTO_Array[stoId].getNumberOfTiers(), _tokensPerTierTotal[stoId].length, @@ -589,7 +589,7 @@ contract("USDTieredSTO", async (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], _endTime[stoId], @@ -626,7 +626,7 @@ contract("USDTieredSTO", async (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", async (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], @@ -683,11 +683,14 @@ contract("USDTieredSTO", async (accounts) => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: ISSUER, gasPrice: GAS_PRICE }); + 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(await USDTieredSTO.at(tx.logs[2].args._module)); + // console.log(I_USDTieredSTO_Array[I_USDTieredSTO_Array.length - 1]); + let tokens = await I_USDTieredSTO_Array[I_USDTieredSTO_Array.length - 1].getUsdTokens.call(); + assert.equal(tokens[0], I_DaiToken.address, "USD Tokens should match"); }); it("Should fail because rates and tier array of different length", async () => { @@ -823,7 +826,8 @@ contract("USDTieredSTO", async (accounts) => { _minimumInvestmentUSD[stoId], _fundRaiseTypes[stoId], _wallet[stoId], - reserveWallet + reserveWallet, + _usdToken[stoId] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -944,11 +948,11 @@ contract("USDTieredSTO", async (accounts) => { await I_USDTieredSTO_Array[stoId].modifyTimes(new BN(tempTime1), new BN(tempTime2), { from: ISSUER }); assert.equal((await I_USDTieredSTO_Array[stoId].startTime.call()).toString(), tempTime1.toString(), "STO Configuration doesn't set as expected"); assert.equal((await I_USDTieredSTO_Array[stoId].endTime.call()).toString(), tempTime2.toString(), "STO Configuration doesn't set as expected"); - + console.log("HERE"); await I_USDTieredSTO_Array[stoId].modifyAddresses( "0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", - address_zero, + [accounts[3]], { from: ISSUER } ); assert.equal( @@ -961,7 +965,7 @@ contract("USDTieredSTO", async (accounts) => { "0x0000000000000000000003000000000000000000", "STO Configuration doesn't set as expected" ); - assert.equal(await I_USDTieredSTO_Array[stoId].usdToken.call(), address_zero, "STO Configuration doesn't set as expected"); + assert.equal((await I_USDTieredSTO_Array[stoId].getUsdTokens())[0], accounts[3], "STO Configuration doesn't set as expected"); }); it("Should fail to change config after endTime", async () => { @@ -984,20 +988,11 @@ contract("USDTieredSTO", async (accounts) => { ) ); - let tempTime1 = await latestTime(); + let tempTime1 = await latestTime() + duration.days(1); let tempTime2 = await 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); }); }); @@ -1041,13 +1036,13 @@ contract("USDTieredSTO", async (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); }); @@ -1090,7 +1085,7 @@ contract("USDTieredSTO", async (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 })); @@ -1099,7 +1094,7 @@ contract("USDTieredSTO", async (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); }); @@ -1146,7 +1141,7 @@ contract("USDTieredSTO", async (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 })); @@ -1155,7 +1150,7 @@ contract("USDTieredSTO", async (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); }); @@ -1204,7 +1199,7 @@ contract("USDTieredSTO", async (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 })); @@ -1213,7 +1208,7 @@ contract("USDTieredSTO", async (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 }); @@ -1221,11 +1216,58 @@ contract("USDTieredSTO", async (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); + }); + + it("should allow changing stable coin address in middle of STO", async () => { + let stoId = 0; + let snapId = await takeSnapshot(); + + // Whitelist + let fromTime = new BN(await latestTime()); + let toTime = fromTime.add(new BN(duration.days(15))); + let expiryTime = toTime.add(new BN(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); }); @@ -1271,7 +1313,7 @@ contract("USDTieredSTO", async (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 })); @@ -1280,7 +1322,7 @@ contract("USDTieredSTO", async (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); }); @@ -1333,7 +1375,7 @@ contract("USDTieredSTO", async (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 })); @@ -1342,7 +1384,7 @@ contract("USDTieredSTO", async (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); }); @@ -1375,20 +1417,31 @@ contract("USDTieredSTO", async (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(); + console.log(totalStatus); + 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 })); }); @@ -1396,10 +1449,12 @@ contract("USDTieredSTO", async (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"); }); }); @@ -1732,7 +1787,7 @@ contract("USDTieredSTO", async (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 }); @@ -1796,6 +1851,11 @@ contract("USDTieredSTO", async (accounts) => { init_WalletDAIBal.add(investment_DAI).toString(), "Wallet DAI Balance not changed as expected" ); + assert.equal( + (await I_USDTieredSTO_Array[stoId].stableCoinsRaised.call(I_DaiToken.address)).toString(), + investment_DAI.toString(), + "DAI Raised not changed as expected" + ); }); it("should successfully buy using fallback at tier 0 for ACCREDITED1", async () => { @@ -2103,14 +2163,24 @@ contract("USDTieredSTO", async (accounts) => { await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(new BN(2))], { from: ISSUER }); - console.log("Current limit: " + (await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride(NONACCREDITED1)).toString()); + let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); + console.log("Current limit: " + investorStatus[2].toString()); + 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].toString(), _nonAccreditedLimitUSD[stoId].div(new BN(2)), "override match"); + assert.equal(totalStatus[2][1].toString(), 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); @@ -2723,7 +2793,7 @@ contract("USDTieredSTO", async (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 = new BN(GAS_PRICE).mul(new BN(tx2.receipt.gasUsed)); console.log(" Gas buyWithUSD: ".grey + new BN(tx2.receipt.gasUsed).toString().grey); @@ -2962,7 +3032,7 @@ contract("USDTieredSTO", async (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 @@ -2980,7 +3050,7 @@ contract("USDTieredSTO", async (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 }) ); }); @@ -3798,7 +3868,7 @@ contract("USDTieredSTO", async (accounts) => { let init_WalletETHBal = new BN(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]; + let tokensToMint = (await I_USDTieredSTO_Array[stoId].buyWithPOLY.call(ACCREDITED1, investment_POLY, {from: ACCREDITED1}))[2]; // Buy With POLY let tx2 = await I_USDTieredSTO_Array[stoId].buyWithPOLY(ACCREDITED1, investment_POLY, { diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 2e5fd4e5f..e4f9db8e1 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -90,7 +90,7 @@ contract("USDTieredSTO Sim", async (accounts) => { let _wallet = []; let _reserveWallet = []; let _usdToken = []; - + const address_zero = "0x0000000000000000000000000000000000000000"; const one_address = "0x0000000000000000000000000000000000000001"; @@ -157,8 +157,8 @@ contract("USDTieredSTO Sim", async (accounts) => { name: "_reserveWallet" }, { - type: "address", - name: "_usdToken" + type: "address[]", + name: "_usdTokens" } ] }; @@ -256,7 +256,7 @@ contract("USDTieredSTO Sim", async (accounts) => { 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 tx = await I_STRProxied.generateSecurityToken(NAME, SYMBOL, TOKENDETAILS, true, { from: ISSUER }); assert.equal(tx.logs[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); @@ -302,7 +302,7 @@ contract("USDTieredSTO Sim", async (accounts) => { _fundRaiseTypes[stoId], _wallet[stoId], _reserveWallet[stoId], - _usdToken[stoId] + [_usdToken[stoId]] ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); @@ -608,7 +608,7 @@ contract("USDTieredSTO Sim", async (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( @@ -691,7 +691,7 @@ contract("USDTieredSTO Sim", async (accounts) => { .yellow ); } else if (isDai && investment_DAI.gt(new BN(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 = new BN(GAS_PRICE).mul(new BN(tx.receipt.gasUsed)); console.log( `buyWithUSD: ${investment_Token.div(e18)} tokens for ${investment_DAI.div(e18)} DAI by ${_investor}` @@ -731,43 +731,43 @@ contract("USDTieredSTO Sim", async (accounts) => { // console.log('final_TokenSupply: '+final_TokenSupply.div(10**18).toNumber()); if (isPoly) { - assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); - assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); - assertIsNear(final_InvestorETHBal, init_InvestorETHBal.sub(gasCost), "Investor ETH Balance not changed as expected" ); - assertIsNear(final_InvestorPOLYBal, init_InvestorPOLYBal.sub(investment_POLY), "Investor POLY Balance not changed as expected" ); - assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); - assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); - assertIsNear(final_STOPOLYBal, init_STOPOLYBal, "STO POLY Balance not changed as expected" ); - assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); - assertIsNear(final_RaisedETH, init_RaisedETH, "Raised ETH not changed as expected"); - assertIsNear(final_RaisedPOLY, init_RaisedPOLY.add(investment_POLY), "Raised POLY not changed as expected" ); - assertIsNear(final_WalletETHBal, init_WalletETHBal, "Wallet ETH Balance not changed as expected" ); - assertIsNear(final_WalletPOLYBal, init_WalletPOLYBal.add(investment_POLY), "Wallet POLY Balance not changed as expected" ); - } else if (isDai) { - assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); - assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); - assertIsNear(final_InvestorETHBal, init_InvestorETHBal.sub(gasCost), "Investor ETH Balance not changed as expected" ); - assertIsNear(final_InvestorDAIBal, init_InvestorDAIBal.sub(investment_DAI), "Investor DAI Balance not changed as expected" ); - assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); - assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); - assertIsNear(final_STODAIBal, init_STODAIBal, "STO DAI Balance not changed as expected" ); - assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); - assertIsNear(final_RaisedETH, init_RaisedETH, "Raised ETH not changed as expected"); - assertIsNear(final_RaisedDAI, init_RaisedDAI.add(investment_DAI), "Raised DAI not changed as expected" ); - assertIsNear(final_WalletETHBal, init_WalletETHBal, "Wallet ETH Balance not changed as expected" ); - assertIsNear(final_WalletDAIBal, init_WalletDAIBal.add(investment_DAI), "Wallet DAI Balance not changed as expected" ); - } else { - assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); - assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); - assertIsNear(final_InvestorETHBal, init_InvestorETHBal .sub(gasCost) .sub(investment_ETH) , "Investor ETH Balance not changed as expected" ); - assertIsNear(final_InvestorPOLYBal, init_InvestorPOLYBal, "Investor POLY Balance not changed as expected" ); - assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); - assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); - assertIsNear(final_STOPOLYBal, init_STOPOLYBal, "STO POLY Balance not changed as expected" ); - assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); - assertIsNear(final_RaisedETH, init_RaisedETH.add(investment_ETH), "Raised ETH not changed as expected" ); - assertIsNear(final_RaisedPOLY, init_RaisedPOLY, "Raised POLY not changed as expected" ); - assertIsNear(final_WalletETHBal, init_WalletETHBal.add(investment_ETH), "Wallet ETH Balance not changed as expected" ); + assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); + assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); + assertIsNear(final_InvestorETHBal, init_InvestorETHBal.sub(gasCost), "Investor ETH Balance not changed as expected" ); + assertIsNear(final_InvestorPOLYBal, init_InvestorPOLYBal.sub(investment_POLY), "Investor POLY Balance not changed as expected" ); + assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); + assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); + assertIsNear(final_STOPOLYBal, init_STOPOLYBal, "STO POLY Balance not changed as expected" ); + assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); + assertIsNear(final_RaisedETH, init_RaisedETH, "Raised ETH not changed as expected"); + assertIsNear(final_RaisedPOLY, init_RaisedPOLY.add(investment_POLY), "Raised POLY not changed as expected" ); + assertIsNear(final_WalletETHBal, init_WalletETHBal, "Wallet ETH Balance not changed as expected" ); + assertIsNear(final_WalletPOLYBal, init_WalletPOLYBal.add(investment_POLY), "Wallet POLY Balance not changed as expected" ); + } else if (isDai) { + assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); + assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); + assertIsNear(final_InvestorETHBal, init_InvestorETHBal.sub(gasCost), "Investor ETH Balance not changed as expected" ); + assertIsNear(final_InvestorDAIBal, init_InvestorDAIBal.sub(investment_DAI), "Investor DAI Balance not changed as expected" ); + assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); + assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); + assertIsNear(final_STODAIBal, init_STODAIBal, "STO DAI Balance not changed as expected" ); + assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); + assertIsNear(final_RaisedETH, init_RaisedETH, "Raised ETH not changed as expected"); + assertIsNear(final_RaisedDAI, init_RaisedDAI.add(investment_DAI), "Raised DAI not changed as expected" ); + assertIsNear(final_WalletETHBal, init_WalletETHBal, "Wallet ETH Balance not changed as expected" ); + assertIsNear(final_WalletDAIBal, init_WalletDAIBal.add(investment_DAI), "Wallet DAI Balance not changed as expected" ); + } else { + assertIsNear(final_TokenSupply, init_TokenSupply.add(investment_Token), "Token Supply not changed as expected" ); + assertIsNear(final_InvestorTokenBal, init_InvestorTokenBal.add(investment_Token), "Investor Token Balance not changed as expected" ); + assertIsNear(final_InvestorETHBal, init_InvestorETHBal .sub(gasCost) .sub(investment_ETH) , "Investor ETH Balance not changed as expected" ); + assertIsNear(final_InvestorPOLYBal, init_InvestorPOLYBal, "Investor POLY Balance not changed as expected" ); + assertIsNear(final_STOTokenSold, init_STOTokenSold.add(investment_Token), "STO Token Sold not changed as expected" ); + assertIsNear(final_STOETHBal, init_STOETHBal, "STO ETH Balance not changed as expected" ); + assertIsNear(final_STOPOLYBal, init_STOPOLYBal, "STO POLY Balance not changed as expected" ); + assertIsNear(final_RaisedUSD, init_RaisedUSD.add(investment_USD), "Raised USD not changed as expected" ); + assertIsNear(final_RaisedETH, init_RaisedETH.add(investment_ETH), "Raised ETH not changed as expected" ); + assertIsNear(final_RaisedPOLY, init_RaisedPOLY, "Raised POLY not changed as expected" ); + assertIsNear(final_WalletETHBal, init_WalletETHBal.add(investment_ETH), "Wallet ETH Balance not changed as expected" ); assertIsNear(final_WalletPOLYBal, init_WalletPOLYBal, "Wallet POLY Balance not changed as expected" ); } } diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index bd4161b2f..0854d94e1 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -49,7 +49,7 @@ contract("SecurityTokenRegistryProxy", async (accounts) => { const decimals = 18; const transferManagerKey = 2; - + const address_zero = "0x0000000000000000000000000000000000000000"; const one_address = "0x0000000000000000000000000000000000000001"; const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; @@ -134,12 +134,12 @@ contract("SecurityTokenRegistryProxy", async (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")), + await I_STRProxied.getUintValue.call(web3.utils.soliditySha3("tickerRegFee")), web3.utils.toWei("250") ); }); @@ -156,7 +156,7 @@ contract("SecurityTokenRegistryProxy", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 19ddab75b..3c52dc693 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -129,12 +129,12 @@ contract("ModuleRegistryProxy", async (accounts) => { // STEP 4: Deploy the GeneralTransferManagerFactory let I_GeneralTransferManagerLogic = await GeneralTransferManagerLogic.new( - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + address_zero, + address_zero, { from: account_polymath } ); - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(0, new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(new BN(0), new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { from: account_polymath }); @@ -158,11 +158,11 @@ contract("ModuleRegistryProxy", async (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); }); }); diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js new file mode 100644 index 000000000..0be2bfe04 --- /dev/null +++ b/test/w_lockup_transfer_manager.js @@ -0,0 +1,966 @@ +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'); +let BN = Web3.utils.BN; +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; + + 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 = new BN(web3.utils.toWei("250")); + let currentTime; + + before(async() => { + currentTime = new BN(await latestTime()); + // 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, 0); + // STEP 4(d): Deploy the LockUpVolumeRestrictionTMFactory + [P_LockUpTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, new BN(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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toString(), 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 = await 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[2].args._ticker, symbol2.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken_div = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + const log = (await I_SecurityToken_div.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toString(), 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 + console.log(account_investor1); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + currentTime, + currentTime, + currentTime.add(new BN(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, new BN(web3.utils.toWei('2', 'ether')), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(account_investor1)).toString(), + 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, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + 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, "0x", new BN(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, new BN(web3.utils.toWei("500", "ether")), {from: token_owner}); + console.log((await P_LockUpTransferManagerFactory.getSetupCost.call()).toString()); + const tx = await I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toString(), 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 = await 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, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toString(), 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 = await 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, "0x", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toString(), 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 = await LockUpTransferManager.at(tx.logs[2].args._module); + }); + + it("Add a new token holder", async() => { + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + 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)).toString(), + 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, + currentTime.add(new BN(duration.seconds(1))), + new BN(duration.seconds(400000)), + new BN(duration.seconds(100000)), + web3.utils.fromAscii("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, + new BN(web3.utils.toWei('1', 'ether')), + currentTime.add(new BN(duration.seconds(1))), + new BN(duration.seconds(400000)), + 0, + web3.utils.fromAscii("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, + new BN(web3.utils.toWei('1', 'ether')), + currentTime.add(new BN(duration.seconds(1))), + 0, + new BN(duration.seconds(100000)), + web3.utils.fromAscii("a_lockup"), + { + from: token_owner + } + ) + ); + }); + + it("Should add the lockup type -- fail because of bad owner", async() => { + await catchRevert( + I_LockUpTransferManager.addNewLockUpType( + new BN(web3.utils.toWei('12', 'ether')), + currentTime.add(new BN(duration.days(1))), + 60, + 20, + web3.utils.fromAscii("a_lockup"), + { + from: account_investor1 + } + ) + ); + }) + + it("Should add the new lockup type", async() => { + let tx = await I_LockUpTransferManager.addNewLockUpType( + new BN(web3.utils.toWei('12', 'ether')), + currentTime.add(new BN(duration.days(1))), + 60, + 20, + web3.utils.fromAscii("a_lockup"), + { + from: token_owner + } + ); + assert.equal((tx.logs[0].args._lockupAmount).toString(), 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'), + currentTime.add(new BN(duration.seconds(1))), + new BN(duration.seconds(400000)), + new BN(duration.seconds(100000)), + web3.utils.fromAscii("a_lockup"), + { + from: token_owner + } + ) + ); + }) + + it("Should allow the creation of a lockup where the lockup amount is divisible" , async() => { + // create a lockup + currentTime = new BN(await latestTime()); + let tx = await I_LockUpVolumeRestrictionTM_div.addNewLockUpToUser( + account_investor1, + web3.utils.toWei('0.5', 'ether'), + currentTime.add(new BN(duration.seconds(1))), + new BN(duration.seconds(400000)), + new BN(duration.seconds(100000)), + web3.utils.fromAscii("a_lockup"), + { + from: token_owner + } + ); + assert.equal(tx.logs[1].args._userAddress, account_investor1); + assert.equal((tx.logs[0].args._lockupAmount).toString(), 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, + new BN(web3.utils.toWei('64951', 'ether')), + currentTime.add(new BN(duration.seconds(1))), + new BN(duration.seconds(400000)), + new BN(duration.seconds(100000)), + web3.utils.fromAscii("b_lockup"), + { + from: token_owner + } + ); + assert.equal(tx.logs[1].args._userAddress, account_investor1); + assert.equal((tx.logs[0].args._lockupAmount).toString(), 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.div(new BN(1).mul(new BN(10).pow(new BN(18)))).toString()); + // 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, + currentTime.add(new BN(duration.seconds(1))), + 60, + 20, + web3.utils.fromAscii("b_lockup"), + { + from: token_owner + } + ); + await increaseTime(2); + let tx = await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("b_lockup")); + console.log("Amount get unlocked:", (tx[4].toString())); + 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(web3.utils.fromAscii("b_lockup")); + console.log("Amount get unlocked:", (tx[4].toString())); + 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(web3.utils.fromAscii("b_lockup")); + console.log("Amount get unlocked:", (tx[4].toString())); + 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(web3.utils.fromAscii("b_lockup")); + console.log("Amount get unlocked:", (tx[4].toString())); + 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(web3.utils.fromAscii("b_lockup")); + console.log("Amount get unlocked:", (tx[4].toString())); + 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)).toString(), + 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)).toString(), + 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)).toString()); + await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); + assert.equal( + (await I_SecurityToken.balanceOf(account_investor2)).toString(), + 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")], + [currentTime.add(new BN(duration.seconds(1))), currentTime.add(new BN(duration.seconds(21)))], + [60, 45], + [20, 15], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("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], + [], + [currentTime.add(new BN(duration.seconds(1))), currentTime.add(new BN(duration.seconds(21)))], + [60, 45], + [20, 15], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.seconds(1))), currentTime.add(new BN(duration.seconds(21)))], + [60, 45, 50], + [20, 15], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.seconds(1))), currentTime.add(new BN(duration.seconds(21)))], + [60, 45, 50], + [20, 15, 10], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("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")], + [currentTime.add(new BN(duration.seconds(1))), currentTime.add(new BN(duration.seconds(21)))], + [60, 45], + [20, 15], + [web3.utils.fromAscii("c_lockup")], + { + from: token_owner + } + ) + ); + }); + + it("Should add the multiple lockup to a address", async() => { + currentTime = new BN(await latestTime()); + await I_LockUpTransferManager.addNewLockUpToUserMulti( + [account_investor3, account_investor3], + [web3.utils.toWei("6", "ether"), web3.utils.toWei("3", "ether")], + [currentTime.add(new BN(duration.seconds(1))), currentTime.add(new BN(duration.seconds(21)))], + [60, 45], + [20, 15], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("d_lockup")], + { + from: token_owner + } + ); + + await increaseTime(1); + let tx = await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("c_lockup")); + let tx2 = await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("d_lockup")); + console.log("Total Amount get unlocked:", (tx[4].toString()) + (tx2[4].toString())); + 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)).toString(), + 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], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("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], + [web3.utils.fromAscii("c_lockup"), web3.utils.fromAscii("e_lockup")], + { + from: account_polymath + } + ) + ); + }) + + it("Should remove the multiple lockup", async() => { + await I_LockUpTransferManager.removeLockUpFromUserMulti( + [account_investor3, account_investor3], + [web3.utils.fromAscii("d_lockup"), web3.utils.fromAscii("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"), + currentTime.add(new BN(duration.minutes(5))), + 60, + 20, + web3.utils.fromAscii("z_lockup"), + { + from: token_owner + } + ); + + await catchRevert( + // edit the lockup + I_LockUpTransferManager.modifyLockUpType( + web3.utils.toWei("9"), + currentTime.add(new BN(duration.seconds(1))), + 60, + 20, + web3.utils.fromAscii("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"), + currentTime.add(new BN(duration.seconds(50))), + 60, + 20, + web3.utils.fromAscii("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"), + currentTime.add(new BN(duration.seconds(50))), + 60, + 20, + web3.utils.fromAscii("m_lockup"), + { + from: token_owner + } + ) + ) + }) + + it("should successfully modify the lockup", async() => { + // edit the lockup + currentTime = new BN(await latestTime()); + await I_LockUpTransferManager.modifyLockUpType( + web3.utils.toWei("9"), + currentTime.add(new BN(duration.seconds(50))), + 60, + 20, + web3.utils.fromAscii("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.div(new BN(1).mul(new BN(10).pow(new BN(18)))).toString()); + + // 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, + currentTime.add(new BN(duration.minutes(5))), + 60, + 20, + web3.utils.fromAscii("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(web3.utils.fromAscii("f_lockup")); + console.log(lockUp); + // elements in lockup array are uint lockUpPeriodSeconds, uint releaseFrequencySeconds, uint startTime, uint totalAmount + assert.equal( + lockUp[0].div(new BN(1).mul(new BN(10).pow(new BN(18)))).toString(), + balance.div(new BN(1).mul(new BN(10).pow(new BN(18)))).toString() + ); + assert.equal(lockUp[2].toString(), 60); + assert.equal(lockUp[3].toString(), 20); + assert.equal(lockUp[4].toString(), 0); + + // edit the lockup + temp = currentTime.add(new BN(duration.seconds(1))); + await I_LockUpTransferManager.modifyLockUpType( + balance, + temp, + 60, + 20, + web3.utils.fromAscii("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(web3.utils.fromAscii("f_lockup")); + console.log(lockUp[4].div(new BN(1).mul(new BN(10).pow(new BN(18)))).toString()); + // edit the lockup + await I_LockUpTransferManager.modifyLockUpType( + balance, + currentTime.add(new BN(duration.days(10))), + 90, + 30, + web3.utils.fromAscii("f_lockup"), + { + from: token_owner + } + ); + }); + + it("Should remove the lockup multi", async() => { + await I_LockUpTransferManager.addNewLockUpTypeMulti( + [web3.utils.toWei("10"), web3.utils.toWei("16")], + [currentTime.add(new BN(duration.days(1))), currentTime.add(new BN(duration.days(1)))], + [50000, 50000], + [10000, 10000], + [web3.utils.fromAscii("k_lockup"), web3.utils.fromAscii("l_lockup")], + { + from: token_owner + } + ); + + // removing the lockup type + let tx = await I_LockUpTransferManager.removeLockupType(web3.utils.fromAscii("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, web3.utils.fromAscii("l_lockup"), {from: token_owner}); + + // try to delete the lockup but fail + + await catchRevert( + I_LockUpTransferManager.removeLockupType(web3.utils.fromAscii("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(web3.utils.fromAscii("foo")); + 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 5b2a4f8e8..000000000 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ /dev/null @@ -1,793 +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"); -let BN = Web3.utils.BN; -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port - -contract("LockupVolumeRestrictionTransferManager", async (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 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; - let I_STRGetter - - // 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 = new BN(web3.utils.toWei("250")); - - let currentTime; - const address_zero = "0x0000000000000000000000000000000000000000"; - const one_address = "0x0000000000000000000000000000000000000001"; - - before(async () => { - currentTime = new BN(await latestTime()); - 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, - I_STRGetter - ] = instances; - - // STEP 4(c): Deploy the VolumeRestrictionTransferManager - [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, 0); - // STEP 4(d): Deploy the VolumeRestrictionTransferManager - [P_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified( - account_polymath, - I_MRProxied, - new BN(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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); - - I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - - const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; - - // 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 = await 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, - currentTime, - currentTime, - currentTime.add(new BN(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, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); - }); - - it("Should Buy some more tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor2, - currentTime, - currentTime, - currentTime.add(new BN(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, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); - }); - - it("Should unsuccessfully attach the VolumeRestrictionTransferManager factory with the security token -- failed because Token is not paid", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); - await catchRevert( - I_SecurityToken.addModule(P_VolumeRestrictionTransferManagerFactory.address, new BN(0), new BN(web3.utils.toWei("500", "ether")), new BN(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, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); - const tx = await I_SecurityToken.addModule( - P_VolumeRestrictionTransferManagerFactory.address, - new BN(0), - new BN(web3.utils.toWei("500", "ether")), - new BN(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 = await 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, new BN(0), new BN(0), new BN(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 = await VolumeRestrictionTransferManager.at(tx.logs[2].args._module); - }); - - it("Add a new token holder", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor3, - currentTime, - currentTime, - currentTime.add(new BN(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, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); - }); - - 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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("3", "ether")).toString()); - }); - - 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, new BN(0), new BN(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, new BN(0), new BN(0), new BN(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, new BN(0), 4, new BN(0), new BN(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, new BN(0), new BN(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, new BN(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, - new BN(web3.utils.toWei("16", "ether")), - 4, - new BN(0), - new BN(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, new BN(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.div(new BN(1).mul(new BN(10).pow(new BN(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, new BN(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, - new BN(web3.utils.toWei("1", "ether")), - new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(0), 8, 4, new BN(0), balance, { from: token_owner }); - - // attempt a transfer - await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(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, new BN(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, new BN(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, new BN(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, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); - - await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(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, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); - await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("5", "ether")), { from: account_investor3 }); - - balancesAfter[account_investor2] = await I_SecurityToken.balanceOf(account_investor2); - assert.equal( - balancesBefore[account_investor2].sub(new BN(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(new BN(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], - [new BN(web3.utils.toWei("1", "ether")), new BN(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, new BN(0), { from: token_owner }); - await I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, new BN(0), { from: token_owner }); - lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); - assert.equal(lockUpsLength, 0); - - let now = await 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, new BN(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 = await 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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, - new BN(web3.utils.toWei("5", "ether")), - new BN(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, new BN(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, new BN(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, new BN(0), new BN(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, new BN(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, new BN(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, new BN(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, new BN(web3.utils.toWei("8", "ether")), { from: account_investor2 }); - - // let's add another lockup to stack them - await I_VolumeRestrictionTransferManager.addLockUp(account_investor1, 16, 4, new BN(0), new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - - balance = await I_SecurityToken.balanceOf(account_investor1); - assert.equal(balance.toString(), new BN(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/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/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js new file mode 100644 index 000000000..0b5456a0d --- /dev/null +++ b/test/y_volume_restriction_tm.js @@ -0,0 +1,1693 @@ +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 BN = Web3.utils.BN; +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; + let toTime; + let expiryTime; + + 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 = web3.utils.toHex("Hello I am legit delegate"); + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + let tempAmount = new BN(0); + let tempArray = new Array(); + let tempArray3 = new Array(); + let tempArrayGlobal = new Array(); + + // Initial fee for ticker registry and security token registry + const initRegFee = new BN(web3.utils.toWei("250")); + + const address_zero = "0x0000000000000000000000000000000000000000"; + + async function print(data, account) { + console.log(` + Latest timestamp: ${data[0].toString()} + SumOfLastPeriod: ${web3.utils.fromWei(data[1]).toString()} + Days Covered: ${data[2].toString()} + Latest timestamp daily: ${data[3].toString()} + Individual Total Trade on latestTimestamp : ${web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[0])) + .toString()} + Individual Total Trade on daily latestTimestamp : ${web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[3])) + .toString()} + `) + } + + async function getLatestTime() { + return new BN(await latestTime()); + } + + async function printRestrictedData(data) { + let investors = data[0]; + for (let i = 0 ; i < investors.length; i++) { + console.log(` + Token holder: ${data[0][i]} + Start Time: ${data[2][i].toString()} + Rolling Period In Days: ${data[3][i].toString()} + End Time : ${data[4][i].toString()} + Allowed Tokens: ${web3.utils.fromWei(data[1][i].toString())} + Type of Restriction: ${data[5][i].toString()} + `) + } + } + + 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() => { + let newLatestTime = await getLatestTime(); + fromTime = newLatestTime; + toTime = newLatestTime; + expiryTime = toTime.add(new BN(duration.days(15))); + // 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, 0); + // STEP 6: Deploy the VolumeRestrictionTMFactory + [P_VolumeRestrictionTMFactory] = await deployVRTMAndVerifyed(account_polymath, I_MRProxied, new BN(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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toString(), 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 = await GeneralTransferManager.at(moduleData); + }); + }); + + describe("Attach the VRTM", async() => { + it("Deploy the VRTM and attach with the ST", async()=> { + let tx = await I_SecurityToken.addModule(I_VolumeRestrictionTMFactory.address, "0x0", new BN(0), new BN(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 = await VolumeRestrictionTM.at(tx.logs[2].args._module); + }); + + it("Transfer some tokens to different account", async() => { + // Add tokens in to the whitelist + let newLatestTime = await getLatestTime(); + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor1, account_investor2, account_investor3], + [newLatestTime, newLatestTime, newLatestTime], + [newLatestTime, newLatestTime, newLatestTime], + [newLatestTime.add(new BN(duration.days(60))), newLatestTime.add(new BN(duration.days(60))), newLatestTime.add(new BN(duration.days(60)))], + [true, true, true], + { + from: token_owner + } + ); + + // Mint some tokens and transferred to whitelisted addresses + await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("40", "ether")), {from: token_owner}); + await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("30", "ether")), {from: token_owner}); + await I_SecurityToken.mint(account_investor3, new BN(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.toString()).toString()), 40); + assert.equal(web3.utils.fromWei((bal2.toString()).toString()), 30); + + }); + + it("Should transfer the tokens freely without any restriction", async() => { + await I_SecurityToken.transfer(account_investor3, new BN(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.toString()).toString()), 35); + }); + }) + + describe("Test for the addIndividualRestriction", async() => { + it("Should add the restriction -- failed because of bad owner", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("12")), + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(duration.days(10))), + 0, + { + from: account_polymath + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e invalid restriction type", async() => { + let newLatestTime = await getLatestTime(); + + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("12")), + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + 0, + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + 0, + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("10")), + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(duration.days(10))), + 1, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("10")), + newLatestTime.sub(new BN(duration.seconds(5))), + 3, + newLatestTime.add(new BN(duration.days(10))), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should add the restriction -- failed because of bad parameters i.e invalid dates", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("10")), + newLatestTime.add(new BN(duration.days(2))), + 3, + newLatestTime.add(new BN(duration.days(1))), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("10")), + newLatestTime.add(new BN(duration.days(2))), + 0, + newLatestTime.add(new BN(duration.days(10))), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("10")), + newLatestTime.add(new BN(duration.days(2))), + 366, + newLatestTime.add(new BN(duration.days(10))), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction -- failed because of bad parameters i.e invalid rolling period", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("10")), + newLatestTime.add(new BN(duration.days(2))), + 3, + newLatestTime.add(new BN(duration.days(3))), + 0, + { + from: token_owner + } + ) + ); + }); + + it("Should add the restriction succesfully", async() => { + let newLatestTime = await getLatestTime(); + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("12")), + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(duration.days(5))), + 0, + { + 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.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0][0], account_investor1); + }); + + it("Should add the restriction for multiple investor -- failed because of bad owner", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3,4,5], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3,4,5], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3,4,5], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3,4,5], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3, 4, 5], + [newLatestTime.add(new BN(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() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2))), newLatestTime.add(new BN(duration.seconds(2)))], + [3, 4, 5], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(duration.days(7)))], + [], + { + from: token_owner + } + ) + ) + }); + + it("Should add the restriction for multiple investor successfully", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor2, account_delegate3, account_investor4], + [new BN(web3.utils.toWei("12")), new BN(web3.utils.toWei("10")), new BN(web3.utils.toWei("15"))], + [0, 0, 0], + [3, 4, 5], + [newLatestTime.add(new BN(duration.days(5))), newLatestTime.add(new BN(duration.days(6))), newLatestTime.add(new BN(duration.days(7)))], + [0,0,0], + { + from: token_owner + } + ); + assert.equal((await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor2))[2].toString(), 3); + assert.equal((await I_VolumeRestrictionTM.getIndividualRestriction.call(account_delegate3))[2].toString(), 4); + assert.equal((await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor4))[2].toString(), 5); + + let data = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0].length, 4); + }); + + it("Should remove the restriction multi -- failed because of address is 0", async() => { + await catchRevert( + I_VolumeRestrictionTM.removeIndividualRestrictionMulti( + [address_zero, 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.getIndividualRestriction.call(account_investor2))[3].toString(), 0); + let data = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0].length, 3); + for (let i = 0; i < data[0].length; i++) { + assert.notEqual(data[0][i], account_investor2); + } + }); + + 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 + } + ) + let data = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0].length, 1); + }); + + it("Should add the restriction succesfully after the expiry of previous one for investor 1", async() => { + await increaseTime(duration.days(5.1)); + let newLatestTime = await getLatestTime(); + console.log( + `Estimated gas for addIndividualRestriction: + ${await I_VolumeRestrictionTM.addIndividualRestriction.estimateGas( + account_investor1, + new BN(web3.utils.toWei("12")), + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(duration.days(6))), + 0, + { + from: token_owner + } + )} + `); + newLatestTime = await getLatestTime(); + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + new BN(web3.utils.toWei("12")), + newLatestTime.add(new BN(duration.seconds(2))), + 3, + newLatestTime.add(new BN(duration.days(6))), + 0, + { + 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.getRestrictionData.call(); + await printRestrictedData(data); + 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() => { + await increaseTime(duration.seconds(10)); + await catchRevert( + I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("13")), { from: account_investor1}) + ); + }); + + 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, new BN(web3.utils.toWei('.3', "ether")), "0x0", false); + assert.equal(result.toString(), 1); + // Perform the transaction + console.log(` + Gas estimation (Individual): ${await I_SecurityToken.transfer.estimateGas(account_investor3, new BN(web3.utils.toWei('.3', "ether")), {from: account_investor1})}` + ); + await I_SecurityToken.transfer(account_investor3, new BN(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.toString()).toString()), 34.7); + + let data = await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor1); + await print(data, account_investor1); + assert.equal( + web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0])), + 0.3 + ); + assert.equal( + data[0].toString(), + (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor1))[1].toString() + ); + assert.equal(web3.utils.fromWei(data[1].toString()), 0.3); + tempArray.push(0.3); + }); + + it("Should fail to add the individual daily restriction -- Bad msg.sender", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei("6")), + newLatestTime.add(new BN(duration.seconds(1))), + newLatestTime.add(new BN(duration.days(4))), + 0, + { + from: account_investor1 + } + ) + ); + }) + + it("Should fail to add the individual daily restriction -- Bad params value", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei("6")), + newLatestTime.add(new BN(duration.seconds(1))), + newLatestTime.add(new BN(duration.days(4))), + 1, + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the individual daily restriction -- Bad params value", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + 0, + newLatestTime.add(new BN(duration.seconds(1))), + newLatestTime.add(new BN(duration.days(4))), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should fail to add the individual daily restriction -- Bad params value", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei("6")), + newLatestTime.add(new BN(duration.days(5))), + newLatestTime.add(new BN(duration.days(4))), + 0, + { + from: token_owner + } + ) + ); + }) + + it("Should add the individual daily restriction for investor 3", async() => { + let newLatestTime = await getLatestTime(); + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei("6")), + newLatestTime.add(new BN(duration.seconds(1))), + newLatestTime.add(new BN(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).toString(), new BN(web3.utils.toWei("6"))); + let data = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0].length, 2); + assert.equal(data[0][1], account_investor3); + let dataRestriction = await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3); + console.log(` + *** Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(18))).toString()} + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + }); + + 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.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + console.log(` + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, new BN(web3.utils.toWei("2")), {from: account_investor3})} + `) + await I_SecurityToken.transfer(account_investor2, new BN(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, new BN(web3.utils.toWei("4")), {from: account_investor3})} + `) + // transfer the 4 tokens which is under the limit + await I_SecurityToken.transfer(account_investor2, new BN(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].toString(), data[3].toString()); + assert.equal(data[3].toString(), startTime); + assert.equal(web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[3])) + , 6); + }); + + it("Should fail to transfer more tokens --because of the above limit", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(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 startTime = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + console.log(` + Gas Estimation for the Individual daily tx - ${await I_SecurityToken.transfer.estimateGas(account_investor2, new BN(web3.utils.toWei("2")), {from: account_investor3})} + `) + await I_SecurityToken.transfer(account_investor2, new BN(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].toString(), new BN(startTime).add(new BN(duration.days(1)))); + assert.equal(web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[3])) + , 2); + }); + + it("Should add the daily restriction on the investor 1", async() => { + let newLatestTime = await getLatestTime(); + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor1, + new BN(5).mul(new BN(10).pow(new BN(16))), + 0, + newLatestTime.add(new BN(duration.days(4))), + 1, + { + from: token_owner + } + ); + + assert.equal(tx.logs[0].args._holder, account_investor1); + assert.equal((tx.logs[0].args._typeOfRestriction).toString(), 1); + assert.equal(web3.utils.fromWei(new BN(tx.logs[0].args._allowedTokens)), 0.05); + let data = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0].length, 3); + assert.equal(data[0][2], account_investor3); + assert.equal(data[0][0], account_investor1); + let dataRestriction = await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor1); + console.log(` + *** Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(16))).toString()} % of TotalSupply + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + }); + + it("Should transfer tokens on the 2nd day by investor1 (Individual + Individual daily)", async() => { + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor1))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor1))[2].toString(); + + console.log(` + Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, new BN(web3.utils.toWei("2")), {from: account_investor1})}` + ); + + await I_SecurityToken.transfer(account_investor2, new BN(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.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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor1, data[0])); + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray)); + assert.equal(data[2].toString(), 1); + assert.equal(data[3].toString(), + (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor1))[1].toString()); + assert.equal(amt, 2); + }); + + 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, new BN(web3.utils.toWei("4")), {from: account_investor1}) + ); + }); + + it("Should add the individual restriction to investor 3", async() => { + let newLatestTime = await getLatestTime(); + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor3, + new BN(1536).mul(new BN(10).pow(new BN(14))), // 15.36 tokens as totalsupply is 1000 + newLatestTime.add(new BN(duration.seconds(2))), + 6, + newLatestTime.add(new BN(duration.days(15))), + 1, + { + from: token_owner + } + ); + + assert.equal(tx.logs[0].args._holder, account_investor3); + assert.equal(tx.logs[0].args._typeOfRestriction, 1); + + let data = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(data); + assert.equal(data[0].length, 4); + assert.equal(data[0][2], account_investor3); + assert.equal(data[0][0], account_investor1); + }); + + 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.getIndividualRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + let startTimeDaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + console.log(` + Gas estimation (Individual + Individual daily): ${await I_SecurityToken.transfer.estimateGas(account_investor2, new BN(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, new BN(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.sub(bal2)).toString()).toString()), 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].toString())) + .div(new BN(10).pow(new BN(18))).toString(); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), 4); + assert.equal(data[2].toString(), 0); + assert.equal(data[3].toString(), new BN(startTimeDaily).add(new BN(duration.days(1)))); + assert.equal(amt, 4); + }); + + it("Should fail during transferring more tokens by investor3 -- Voilating the daily Limit", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(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() => { + // remove the Individual daily restriction + await catchRevert( + 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 dataAdd = await I_VolumeRestrictionTM.getRestrictionData.call(); + await printRestrictedData(dataAdd); + assert.equal(dataAdd[0].length, 3); + assert.equal(dataAdd[0][0], account_investor1); + assert.equal(dataAdd[0][2], account_investor3); + + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + + // transfer more tokens on the same day + await I_SecurityToken.transfer(account_investor2, new BN(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].toString())) + .div(new BN(10).pow(new BN(18))).toString(); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), 8); + assert.equal(data[2].toString(), 0); + assert.equal(data[3].toString(), 0); + assert.equal(amt, 8); + }); + + it("Should add the new Individual daily restriction and transact the tokens", async() => { + let newLatestTime = await getLatestTime(); + // add new restriction + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei("2")), + newLatestTime.add(new BN(duration.days(1))), + newLatestTime.add(new BN(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).toString(), new BN(web3.utils.toWei("2"))); + let dataRestriction = await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3); + console.log(` + *** Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(18))).toString()} + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + // Increase the time by one day + await increaseTime(duration.days(1.1)); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("2")), {from: account_investor3}); + tempArray3.push(2); + + 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].toString())) + .div(new BN(10).pow(new BN(18))).toString(); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 1); + assert.equal(data[3].toString(), dataRestriction[1].toString()); + assert.equal(amt, 2); + + // Fail to sell more tokens than the limit + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("2")), {from: account_investor3}) + ); + }); + + it("Should fail to modify the individual daily restriction -- bad owner", async() => { + let newLatestTime = await getLatestTime(); + await catchRevert( + I_VolumeRestrictionTM.modifyIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei('3')), + newLatestTime, + newLatestTime.add(new BN(duration.days(5))), + 0, + { + from: account_polymath + } + ) + ); + }); + + it("Should modify the individual daily restriction", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.modifyIndividualDailyRestriction( + account_investor3, + new BN(web3.utils.toWei('3')), + 0, + newLatestTime.add(new BN(duration.days(5))), + 0, + { + from: token_owner + } + ); + + let dataRestriction = await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3); + console.log(` + *** Modify Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(18))).toString()} + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + }); + + it("Should allow to sell to transfer more tokens by investor3", async() => { + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 1); + assert.equal(data[3].toString(), startTimedaily); + assert.equal(amt, 5); + }); + + it("Should allow to transact the tokens on the other day", async() => { + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + + await increaseTime(duration.days(1.1)); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 2); + assert.equal(data[3].toString(), new BN(startTimedaily).add(new BN(duration.days(1)))); + assert.equal(amt, 2.36); + }); + + it("Should fail to transfer the tokens after completion of the total amount", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(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, new BN(web3.utils.toWei("10")), {from: token_owner}); + + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 2); + assert.equal(data[3].toString(), new BN(startTimedaily).add(new BN(duration.days(1)))); + assert.equal(amt, 2.86); + }); + + it("Should fail to transact tokens more than the allowed in the second rolling period", async() => { + let newLatestTime = await getLatestTime(); + await increaseTime(duration.days(4)); + let i + for (i = 0; i < 3; i++) { + tempArray3.push(0); + } + console.log(`Diff Days: ${(newLatestTime - ((await I_VolumeRestrictionTM.getIndividualBucketDetailsToUser.call(account_investor3))[0]).toString()) / 86400}`); + let allowedAmount = (tempArray3[0] + 1.1); + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(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.getIndividualRestriction.call(account_investor3))[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + let allowedAmount = (tempArray3[0] + 1); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 6); + assert.equal(data[3].toString(), new BN(startTimedaily).add(new BN(duration.days(1))).toString()); + assert.equal(amt, allowedAmount); + }); + + it("Should sell more tokens on the net day of rolling period", async() => { + await increaseTime(duration.days(3)); + + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + + tempArray3.push(0); + tempArray3.push(0); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 9); + assert.equal(data[3].toString(), new BN(startTimedaily).add(new BN(duration.days(1)))); + assert.equal(amt, 7); + }) + + it("Should transfer after the 5 days", async() => { + await increaseTime(duration.days(4.5)); + + for (let i = 0; i <3; i++) { + tempArray3.push(0); + } + + let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[2].toString(); + + await I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("25")), {from: account_investor2}); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 13); + assert.equal(data[3].toString(), new BN(startTimedaily).add(new BN(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(2)); + await I_SecurityToken.transfer(account_investor2, new BN(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() => { + let newLatestTime = await getLatestTime(); + await I_GeneralTransferManager.modifyWhitelist( + account_investor4, + newLatestTime, + newLatestTime, + newLatestTime.add(new BN(duration.days(30))), + true, + { + from: token_owner + } + ); + }); + + it("Should mint some tokens to investor 4", async() => { + await I_SecurityToken.mint(account_investor4, new BN(web3.utils.toWei("20")), {from: token_owner}); + }); + + it("Should add the default daily restriction successfully", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.addDefaultDailyRestriction( + new BN(275).mul(new BN(10).pow(new BN(14))), + 0, + newLatestTime.add(new BN(duration.days(3))), + 1, + { + from: token_owner + } + ); + + let dataRestriction = await I_VolumeRestrictionTM.getDefaultDailyRestriction.call(); + console.log(` + *** Add Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(16))).toString()} % of TotalSupply + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + }); + + it("Should fail to transfer above the daily limit", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("5")), {from: account_investor4}) + ) + }) + + it("Should transfer the token by investor 4", async() => { + let startTimedaily = (await I_VolumeRestrictionTM.getDefaultDailyRestriction.call())[1].toString(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor4, data[3].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), 0); + assert.equal(data[1].toString(), 0); + assert.equal(data[2].toString(), 0); + assert.equal(data[3].toString(), startTimedaily); + assert.equal(amt, 3.57); + }); + + 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, new BN(web3.utils.toWei("5")), {from: account_investor4}); + assert.equal((tx.logs[0].args.value).toString(), new BN(web3.utils.toWei("5"))); + // Transfer the tokens again to investor 3 + await I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("40")), {from: account_investor2}); + }) + + it("Should successfully add the default restriction", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.addDefaultRestriction( + new BN(web3.utils.toWei("10")), + 0, + 5, + newLatestTime.add(new BN(duration.days(10))), + 0, + { + from: token_owner + } + ); + + let data = await I_VolumeRestrictionTM.getDefaultRestriction.call(); + assert.equal(data[0].toString(), new BN(web3.utils.toWei("10"))); + assert.equal(data[2].toString(), 5); + let dataRestriction = await I_VolumeRestrictionTM.getDefaultRestriction.call(); + console.log(` + *** Add Individual restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(18))).toString()} + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + }); + + 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.getDefaultRestriction.call())[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getDefaultDailyRestriction.call())[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getDefaultRestriction.call())[2].toString(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 0); + assert.equal(data[3].toString(), 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, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 1); + assert.equal(data[3].toString(), 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, new BN(web3.utils.toWei("3")), {from: account_investor3}) + ); + }); + + it("Should able to transfer tokens in the next rolling period", async() => { + let newLatestTime = await getLatestTime(); + await increaseTime(duration.days(4.1)); + console.log(`*** Diff days: ${(newLatestTime - ((await I_VolumeRestrictionTM.getDefaultBucketDetailsToUser.call(account_investor3))[0]).toString()) / 86400}`) + for (let i = 0; i < 3; i++) { + tempArray3.push(0); + } + + let startTime = (await I_VolumeRestrictionTM.getDefaultRestriction.call())[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getDefaultDailyRestriction.call())[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getDefaultRestriction.call())[2].toString(); + + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 5); + assert.equal(data[3].toString(), 0); + assert.equal(amt, 7); + + // Try to transact more on the same day but fail + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1")), {from: account_investor3}) + ); + }); + + it("Should add the daily default restriction again", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.addDefaultDailyRestriction( + new BN(web3.utils.toWei("2")), + 0, + newLatestTime.add(new BN(duration.days(3))), + 0, + { + from: token_owner + } + ); + + let dataRestriction = await I_VolumeRestrictionTM.getDefaultDailyRestriction.call(); + console.log(` + *** Add Individual Daily restriction data *** + Allowed Tokens: ${dataRestriction[0].div(new BN(10).pow(new BN(16))).toString()} + StartTime : ${dataRestriction[1].toString()} + Rolling Period in days : ${dataRestriction[2].toString()} + EndTime : ${dataRestriction[3].toString()} + Type of Restriction: ${dataRestriction[4].toString()} + `); + }); + + it("Should not able to transfer tokens more than the default daily restriction", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("3")), {from: account_investor3}) + ); + }); + + 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.getDefaultRestriction.call())[1].toString(); + let startTimedaily = (await I_VolumeRestrictionTM.getDefaultDailyRestriction.call())[1].toString(); + let rollingPeriod = (await I_VolumeRestrictionTM.getDefaultRestriction.call())[2].toString(); + //sell tokens upto the limit + await I_SecurityToken.transfer(account_investor2, new BN(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 = web3.utils.fromWei(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account_investor3, data[0].toString())); + + // Verify the storage changes + assert.equal(data[0].toString(), new BN(startTime).add(new BN(duration.days(data[2].toString())))); + assert.equal(web3.utils.fromWei(data[1]), await calculateSum(rollingPeriod, tempArray3)); + assert.equal(data[2].toString(), 6); + assert.equal(data[3].toString(), new BN(startTimedaily).add(new BN(duration.days(1)))); + assert.equal(amt, 2); + }); + }) + + 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}); + console.log(await I_VolumeRestrictionTM.getExemptAddress.call()); + let beforeBal = await I_SecurityToken.balanceOf.call(account_investor4); + await I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("3")), {from: account_investor4}); + let afterBal = await I_SecurityToken.balanceOf.call(account_investor4); + let diff = beforeBal.sub(afterBal); + assert.equal(web3.utils.fromWei((diff.toString()).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() => { + + it("Should add the individual restriction for multiple investor", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.addIndividualRestrictionMulti( + [account_investor3, account_delegate3], + [new BN(web3.utils.toWei("15")), new BN(1278).mul(new BN(10).pow(new BN(14)))], + [newLatestTime.add(new BN(duration.days(1))), newLatestTime.add(new BN(duration.days(2)))], + [15, 20], + [newLatestTime.add(new BN(duration.days(40))), newLatestTime.add(new BN(duration.days(60)))], + [0,1], + { + from: token_owner + } + ); + + let indi1 = await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3); + let indi2 = await I_VolumeRestrictionTM.getIndividualRestriction.call(account_delegate3); + + assert.equal(indi1[0].div(new BN(10).pow(new BN(18))).toString(), 15); + assert.equal(indi2[0].div(new BN(10).pow(new BN(14))).toString(), 1278); + + assert.equal(indi1[2].toString(), 15); + assert.equal(indi2[2].toString(), 20); + + assert.equal(indi1[4].toString(), 0); + assert.equal(indi2[4].toString(), 1); + }); + + it("Should modify the details before the starttime passed", async() => { + let newLatestTime = await getLatestTime(); + await I_VolumeRestrictionTM.modifyIndividualRestrictionMulti( + [account_investor3, account_delegate3], + [new BN(1278).mul(new BN(10).pow(new BN(14))), new BN(web3.utils.toWei("15"))], + [newLatestTime.add(new BN(duration.days(1))), newLatestTime.add(new BN(duration.days(2)))], + [20, 15], + [newLatestTime.add(new BN(duration.days(40))), newLatestTime.add(new BN(duration.days(60)))], + [1,0], + { + from: token_owner + } + ); + + let indi1 = await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3); + let indi2 = await I_VolumeRestrictionTM.getIndividualRestriction.call(account_delegate3); + + assert.equal(indi2[0].div(new BN(10).pow(new BN(18))).toString(), 15); + assert.equal(indi1[0].div(new BN(10).pow(new BN(14))).toString(), 1278); + + assert.equal(indi2[2].toString(), 15); + assert.equal(indi1[2].toString(), 20); + + assert.equal(indi2[4].toString(), 0); + assert.equal(indi1[4].toString(), 1); + }); + + }); + + 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, 5); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''), "Maximum Volume"); + }); + }); + +}); diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js new file mode 100644 index 000000000..54e249a1f --- /dev/null +++ b/test/z_blacklist_transfer_manager.js @@ -0,0 +1,996 @@ +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'); +let BN = Web3.utils.BN; +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]); + let currentTime; + + before(async() => { + currentTime = new BN(await latestTime()); + // 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, new BN(0)); + + // STEP 3(a): Deploy the PercentageTransferManager + [I_BlacklistTransferManagerFactory] = await deployBlacklistTMAndVerified(account_polymath, I_MRProxied, new BN(0)); + + // STEP 4(b): Deploy the PercentageTransferManager + [P_BlacklistTransferManagerFactory] = await deployBlacklistTMAndVerified(account_polymath, I_MRProxied, new BN(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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toString(), 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 = await 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].toString(), 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 = await 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 }); + console.log(tx); + assert.equal(tx.logs[2].args._types[0].toString(), 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 = await 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, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + 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, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + 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, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + 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, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + 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, + currentTime, + currentTime, + currentTime.add(new BN(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)).toString(), + web3.utils.toWei('2', 'ether') + ); + }); + + + it("Should add the blacklist", async() => { + //Add the new blacklist + currentTime = new BN(await latestTime()); + let tx = await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("a_blacklist"), 20, { from: token_owner }); + 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() => { + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("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(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii(""), 20, { + from: token_owner + }) + ); + }); + + it("Should fail in adding the blacklist as the start date is invalid", async() => { + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(0, currentTime.add(new BN(3000)), web3.utils.fromAscii("b_blacklist"), 20, { + from: token_owner + }) + ); + }); + + it("Should fail in adding the blacklist as the dates are invalid", async() => { + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(4000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("b_blacklist"), 20, { + from: token_owner + }) + ); + }); + + it("Should fail in adding the blacklist because only owner can add the blacklist", async() => { + await catchRevert( + I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("b_blacklist"), 20, { + from: account_investor1 + }) + ); + }); + + 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(currentTime.add(new BN(1000)), currentTime.add(new BN(duration.days(2))), web3.utils.fromAscii("b_blacklist"), 1, { + from: token_owner + }) + ); + }); + + it("Should add the mutiple blacklist", async() => { + //Add the new blacklist + let startTime = [currentTime.add(new BN(2000)),currentTime.add(new BN(3000))]; + let endTime = [currentTime.add(new BN(5000)),currentTime.add(new BN(8000))]; + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("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._blacklistName; + assert.equal(web3.utils.hexToUtf8(blacklistName), web3.utils.hexToUtf8(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 = [currentTime.add(new BN(2000)),currentTime.add(new BN(3000))]; + let endTime = [currentTime.add(new BN(5000)),currentTime.add(new BN(8000))]; + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("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 = [currentTime.add(new BN(2000)),currentTime.add(new BN(3000))]; + let endTime = [currentTime.add(new BN(5000)),currentTime.add(new BN(8000))]; + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("z_blacklist"),web3.utils.fromAscii("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(currentTime.add(new BN(2000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("a_blacklist"), 20, { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._blacklistName), "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(currentTime.add(new BN(2000)), currentTime.add(new BN(3000)), web3.utils.fromAscii(""), 20, { + from: token_owner + }) + ); + }); + + it("Should fail in modifying the blacklist as the dates are invalid", async() => { + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(currentTime.add(new BN(4000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("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(currentTime.add(new BN(2000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("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(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("a_blacklist"), 20, { + from: account_investor1 + }) + ); + }); + + it("Should fail in modifying the blacklist as blacklist type doesnot exist", async() => { + await catchRevert( + I_BlacklistTransferManager.modifyBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("b_blacklist"), 20, { + from: token_owner + }) + ); + }); + + it("Should modify the mutiple blacklist", async() => { + //Add the new blacklist + let startTime = [currentTime.add(new BN(3000)),currentTime.add(new BN(3000))]; + let endTime = [currentTime.add(new BN(5000)),currentTime.add(new BN(7000))]; + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("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._blacklistName; + assert.equal(web3.utils.hexToUtf8(blacklistName), web3.utils.hexToUtf8(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 = [currentTime.add(new BN(3000)),currentTime.add(new BN(3000))]; + let endTime = [currentTime.add(new BN(5000)),currentTime.add(new BN(7000))]; + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("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 = [currentTime.add(new BN(3000)),currentTime.add(new BN(3000))]; + let endTime = [currentTime.add(new BN(5000)),currentTime.add(new BN(7000))]; + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("z_blacklist"),web3.utils.fromAscii("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, web3.utils.fromAscii("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, web3.utils.fromAscii("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("0x0000000000000000000000000000000000000000", web3.utils.fromAscii("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, web3.utils.fromAscii("b_blacklist"), { + from: token_owner + }) + ); + }); + + it("Should get the list of investors associated to blacklist", async() => { + let perm = await I_BlacklistTransferManager.getListOfAddresses.call(web3.utils.fromAscii("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(web3.utils.fromAscii("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)).toString(), + 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(duration.seconds(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)).toString(), + web3.utils.toWei('4', 'ether') + ); + }); + + it("Should fail in transfer the tokens as the investor in blacklist", async() => { + // Jump time + await increaseTime(duration.days(20) - 1500); + 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)).toString(), + 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}); + currentTime = new BN(await latestTime()); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(500)), currentTime.add(new BN(4000)), web3.utils.fromAscii("k_blacklist"), 8, { from: token_owner }); + + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, web3.utils.fromAscii("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)).toString(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should investor fail in transfer token as it is in blacklist time period", async() => { + + // Jump time + await increaseTime(duration.days(8) - 1000); + //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() => { + currentTime = new BN(await latestTime()); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(5000)), currentTime.add(new BN(8000)), web3.utils.fromAscii("l_blacklist"), 5, { from: token_owner }); + + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor3, web3.utils.fromAscii("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)).toString(), + web3.utils.toWei('3', 'ether') + ); + }); + + it("Should investor fail in transfer token as it is in blacklist time period", async() => { + + // Jump time + await increaseTime(duration.days(5) - 3000); + //Trasfer tokens + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei('1', 'ether'), { + from: account_investor3 + }) + ); + }); + + + it("Should delete the blacklist type", async() => { + currentTime = new BN(await latestTime()); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("b_blacklist"), 20, { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteBlacklistType(web3.utils.fromAscii("b_blacklist"), { from: token_owner }); + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._blacklistName), "b_blacklist", "Failed in deleting the blacklist"); + + }); + + it("Only owner have the permission to delete the blacklist type", async() => { + currentTime = new BN(await latestTime()); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("b_blacklist"), 20, { from: token_owner }); + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistType(web3.utils.fromAscii("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(web3.utils.fromAscii("a_blacklist"), { + from: token_owner + }) + ); + }); + + it("Should fail in deleting the blacklist type as the blacklist doesnot exist", async() => { + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistType(web3.utils.fromAscii("c_blacklist"), { + from: token_owner + }) + ); + }); + + it("Should delete the mutiple blacklist type", async() => { + let name = [web3.utils.fromAscii("y_blacklist"),web3.utils.fromAscii("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._blacklistName; + assert.equal(web3.utils.hexToUtf8(blacklistName), web3.utils.hexToUtf8(name[i]), "Failed in deleting the blacklist"); + } + + }); + + it("Should fail in deleting multiple blacklist type because only owner can do it.", async() => { + let name = [web3.utils.fromAscii("b_blacklist"),web3.utils.fromAscii("a_blacklist")]; + await catchRevert( + I_BlacklistTransferManager.deleteBlacklistTypeMulti(name, { + from: account_investor1 + }) + ); + }); + + it("Should delete the investor from all the associated blacklist", async() => { + currentTime = new BN(await latestTime()); + let data = await I_BlacklistTransferManager.getBlacklistNamesToUser.call(account_investor1); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("g_blacklist"), 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, web3.utils.fromAscii("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,web3.utils.fromAscii("g_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("0x0000000000000000000000000000000000000000", { + 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, web3.utils.fromAscii("g_blacklist"), { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, web3.utils.fromAscii("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; + 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() => { + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, web3.utils.fromAscii("g_blacklist"), { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, web3.utils.fromAscii("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(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("s_blacklist"), 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, web3.utils.fromAscii("s_blacklist"), { from: token_owner }); + // await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, "g_blacklist", { from: token_owner }); + let investor = [account_investor5,account_investor2]; + let blacklistName = [web3.utils.fromAscii("s_blacklist"),web3.utils.fromAscii("g_blacklist")]; + 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; + 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, web3.utils.fromAscii("s_blacklist"), { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor2, web3.utils.fromAscii("g_blacklist"), { from: token_owner }); + let investor = [account_investor5,account_investor2]; + let blacklistName = [web3.utils.fromAscii("s_blacklist"),web3.utils.fromAscii("g_blacklist")]; + await catchRevert( + I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(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 = [web3.utils.fromAscii("s_blacklist"),web3.utils.fromAscii("g_blacklist")]; + await catchRevert( + I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(investor,blacklistName, { + from: token_owner + }) + ); + }); + + it("Should delete the investor from the blacklist type", async() => { + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("f_blacklist"), 20, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, web3.utils.fromAscii("f_blacklist"), { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor5, web3.utils.fromAscii("f_blacklist"), { from: token_owner }); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(500)), currentTime.add(new BN(8000)), web3.utils.fromAscii("q_blacklist"), 10, { from: token_owner }); + await I_BlacklistTransferManager.addInvestorToBlacklist(account_investor1, web3.utils.fromAscii("q_blacklist"), { from: token_owner }); + let tx = await I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, web3.utils.fromAscii("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, web3.utils.fromAscii("f_blacklist"), { from: token_owner }); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, web3.utils.fromAscii("f_blacklist"), { + from: account_investor2 + }) + ); + }); + + it("Should fail in deleting the investor because the investor address is invalid", async() => { + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist("0x0000000000000000000000000000000000000000", web3.utils.fromAscii("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, web3.utils.fromAscii("f_blacklist"), { from: token_owner }); + await catchRevert( + I_BlacklistTransferManager.deleteInvestorFromBlacklist(account_investor1, web3.utils.fromAscii("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, web3.utils.fromAscii(""), { + from: token_owner + }) + ); + }); + + it("Should add investor and new blacklist type", async() => { + let tx = await I_BlacklistTransferManager.addInvestorToNewBlacklist(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("c_blacklist"), 20, account_investor3, { from: token_owner }); + 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"); + + }); + + it("Should fail in adding the investor and new blacklist type", async() => { + await catchRevert( + I_BlacklistTransferManager.addInvestorToNewBlacklist(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("c_blacklist"), 20, account_investor3, { + from: account_investor2 + }) + ); + }); + + it("Should add mutiple investor to blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("d_blacklist"), 20, { from: token_owner }); + let investor = [account_investor4,account_investor5]; + let tx = await I_BlacklistTransferManager.addInvestorToBlacklistMulti([account_investor4,account_investor5], web3.utils.fromAscii("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], web3.utils.fromAscii("b_blacklist"), { + from: account_investor1 + }) + ); + }); + + it("Should add mutiple investor to the mutiple blacklist", async() => { + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("m_blacklist"), 20, { from: token_owner }); + await I_BlacklistTransferManager.addBlacklistType(currentTime.add(new BN(1000)), currentTime.add(new BN(3000)), web3.utils.fromAscii("n_blacklist"), 20, { from: token_owner }); + let investor = [account_investor4,account_investor5]; + let blacklistName =[web3.utils.fromAscii("m_blacklist"),web3.utils.fromAscii("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), web3.utils.hexToUtf8(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 = [ web3.utils.fromAscii("m_blacklist"), web3.utils.fromAscii("n_blacklist")]; + await I_BlacklistTransferManager.deleteMultiInvestorsFromBlacklistMulti(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 =[web3.utils.fromAscii("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.description.call(), + "Automate blacklist to restrict selling", + "Wrong Module added"); + 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(), + "2.1.0", + "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"); + }); + }); + +}); 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..194287801 --- /dev/null +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -0,0 +1,310 @@ +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'); + +// modules for test +const CountTransferManager = artifacts.require("./CountTransferManager"); +const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); +const VolumeRestrictionTransferManager = artifacts.require('./LockUpTransferManager'); +const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); + + + +const Web3 = require('web3'); +const BN = Web3.utils.BN; +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_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; + + + //Define all modules for test + let I_CountTransferManagerFactory; + let I_CountTransferManager; + + let I_ManualApprovalTransferManagerFactory; + let I_ManualApprovalTransferManager; + + let I_VolumeRestrictionTransferManagerFactory; + let I_VolumeRestrictionTransferManager; + + let I_PercentageTransferManagerFactory; + let I_PercentageTransferManager; + + // 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"); + + let _details = "details holding for test"; + let testRepeat = 20; + + // define factories and modules for fuzz test + var factoriesAndModules = [ + { factory: 'I_CountTransferManagerFactory', module: 'CountTransferManager'}, + { factory: 'I_ManualApprovalTransferManagerFactory', module: 'ManualApprovalTransferManager'}, + { factory: 'I_VolumeRestrictionTransferManagerFactory', module: 'VolumeRestrictionTransferManager'}, + { factory: 'I_PercentageTransferManagerFactory', module: 'PercentageTransferManager'}, + ]; + + let totalModules = factoriesAndModules.length; + let bytesSTO; + + + 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, 0); + // STEP 6: Deploy the GeneralDelegateManagerFactory + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500")); + + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); + + // Deploy Modules + [I_CountTransferManagerFactory] = await deployCountTMAndVerifyed(account_polymath, I_MRProxied, 0); + [I_ManualApprovalTransferManagerFactory] = await deployManualApprovalTMAndVerifyed(account_polymath, I_MRProxied, 0); + [I_VolumeRestrictionTransferManagerFactory] = await deployLockupVolumeRTMAndVerified(account_polymath, I_MRProxied, 0); + [I_PercentageTransferManagerFactory] = await deployPercentageTMAndVerified(account_polymath, I_MRProxied, 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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // 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 = await 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, "0x0", 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, + "0x0", + 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 = await 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, "0x0", 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 = await 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 + for (var i = 0; i < testRepeat; i++) { + + console.log("1.2"); + + // 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 == '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 = await 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); + + } + }) + }); + +}); 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..0cf2fc02f --- /dev/null +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -0,0 +1,723 @@ +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 BN = Web3.utils.BN; +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 = currentTime; + let toTime = currentTime; + 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 BN(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].toString()} + SumOfLastPeriod: ${data[1].dividedBy(new BN(10).pow(18)).toString()} + Days Covered: ${data[2].toString()} + Latest timestamp daily: ${data[3].toString()} + Individual Total Trade on latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[0])) + .dividedBy(new BN(10).pow(18)).toString()} + Individual Total Trade on daily latestTimestamp : ${(await I_VolumeRestrictionTM.getTotalTradedByUser.call(account, data[3])) + .dividedBy(new BN(10).pow(18)).toString()} + `) + } + + 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; + } + + async function printIR(data) { + console.log(` + Allowed Tokens : ${web3.utils.fromWei(data[0])} + StartTime : ${data[1].toString()} + Rolling Period : ${data[2].toString()} + EndTime : ${data[3].toString()} + Restriction Type: ${data[4].toString() == 0 ? "Fixed" : "Percentage"} + `) + } + let currentTime; + before(async() => { + // Accounts setup + currentTime = new BN(await latestTime()); + 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, 0); + // STEP 6: Deploy the VolumeRestrictionTMFactory + [P_VolumeRestrictionTMFactory] = await deployVRTMAndVerifyed(account_polymath, I_MRProxied, 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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, { from: token_owner }); + console.log(tx.logs); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toString(), 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 = await GeneralTransferManager.at(moduleData); + }); + }); + + describe("Attach the VRTM", async() => { + it("Deploy the VRTM and attach with the ST", async()=> { + let tx = await I_SecurityToken.addModule(I_VolumeRestrictionTMFactory.address, "0x0", 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 = await VolumeRestrictionTM.at(tx.logs[2].args._module); + }); + + it("Transfer some tokens to different account", async() => { + // Add tokens in to the whitelist + currentTime = new BN(await latestTime()); + await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor1, account_investor2, account_investor3], + [currentTime, currentTime, currentTime], + [currentTime, currentTime, currentTime], + [currentTime.add(new BN(duration.days(60))), currentTime.add(new BN(duration.days(60))), currentTime.add(new BN(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("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}); + + }); + + }); + + 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 = 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 dailyRestrictionAmount = Math.floor(Math.random() * 10); + if ( dailyRestrictionAmount == 0 ) { + dailyRestrictionAmount = 1; + } + var rollingPeriod = 2; + var sumOfLastPeriod = 0; + + console.log("a"); + currentTime = new BN(await latestTime()); + // 1 - add individual restriction with a random number + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei(individualRestrictTotalAmount.toString()), + currentTime.add(new BN(duration.seconds(2))), + rollingPeriod, + currentTime.add(new BN(duration.days(3))), + 0, + { + from: token_owner + } + ); + currentTime = new BN(await latestTime()); + console.log("b"); + tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor1, + web3.utils.toWei(dailyRestrictionAmount.toString()), + currentTime.add(new BN(duration.seconds(1))), + currentTime.add(new BN(duration.days(4))), + 0, + { + from: token_owner + } + ); + + console.log("c"); + var txNumber = 10; // define fuzz test amount for tx within 24 hrs + currentTime = new BN(await latestTime()); + 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) { + 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("2"); + } + + // await revertToSnapshot(snapId); + 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 = 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; + + console.log("a"); + currentTime = new BN(await latestTime()); + // 1 - add individual restriction with a random number + let tx = await I_VolumeRestrictionTM.addIndividualRestriction( + account_investor1, + web3.utils.toWei(individualRestrictTotalAmount.toString()), + currentTime.add(new BN(duration.seconds(1))), + rollingPeriod, + currentTime.add(new BN(duration.days(3))), + 0, + { + from: token_owner + } + ); + currentTime = new BN(await latestTime()); + console.log("b"); + tx = await I_VolumeRestrictionTM.addDefaultRestriction( + account_investor1, + currentTime.add(new BN(duration.seconds(1))), + rollingPeriod, + currentTime.add(new BN(duration.days(4))), + 0, + { + from: token_owner + } + ); + currentTime = new BN(await latestTime()); + console.log("c"); + var txNumber = 10; // define fuzz test amount for tx + + for (var j = 0; j < txNumber; j++) { + await increaseTime(duration.seconds(5)); + currentTime = new BN(await latestTime()); + 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 || 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 = 0; + 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); + if (dailyRestrictionAmount === 0) { + dailyRestrictionAmount = 1; + } + + // add daily restriction + let tx = await I_VolumeRestrictionTM.addIndividualDailyRestriction( + account_investor1, + web3.utils.toWei(dailyRestrictionAmount.toString()), + currentTime.add(new BN(duration.seconds(startTime))), + currentTime.add(new BN(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 < txNumber; j++) { + var timeIncreaseBetweenTx = Math.floor(Math.random() * 10) * 3600; + + await increaseTime(duration.seconds(timeIncreaseBetweenTx)); + currentTime = new BN(await latestTime()); + accumulatedTimeIncrease = timeIncreaseBetweenTx + accumulatedTimeIncrease; + console.log("4"); + + // generate a random amount + var transactionAmount = Math.floor(Math.random() * 10); + + // 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) { + 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"); + } + + } + + }); + + + + + 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); + + 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()), + currentTime.add(new BN(duration.seconds(1))), + rollingPeriod, + currentTime.add(new BN(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)); + currentTime = new BN(await latestTime()); + 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"); + } + }); + + 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("\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(`\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(individualRestrictionTotalAmount.toString()), + currentTime.add(new BN(duration.days(2))), + rollingPeriod, + currentTime.add(new BN(duration.days(5))), + 0, + { + from: token_owner + } + ); + + 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(`\t\t Test number: ${j}\n`); + + // modify IR + var newIR = Math.floor(Math.random() * (10 * precision - 1 * precision) + 1 * precision) / (1*precision); + console.log("Original Restriction"); + printIR(await I_VolumeRestrictionTM.getIndividualRestriction(account_investor1, {from: token_owner})); + currentTime = new BN(await latestTime()); + console.log(`\t\t Modification of the IR with new startTime: ${currentTime + duration.days(1+j)} and new total amount: ${newIR} `.green); + + await I_VolumeRestrictionTM.modifyIndividualRestriction( + account_investor1, + web3.utils.toWei(newIR.toString()), + currentTime.add(new BN(duration.days(1+j))), + rollingPeriod, + currentTime.add(new BN(duration.days(5+j))), + 0, + { from: token_owner } + ); + console.log("Modified Restriction"); + printIR(await I_VolumeRestrictionTM.getIndividualRestriction(account_investor1, {from: token_owner})); + 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 * precision - 1 * precision) + 1 * precision) / (1*precision); + + // check against daily and total restrictions to determine if the transaction should pass or not + console.log("Transaction Amount: " + transactionAmount); + console.log("newIR Amount: " + newIR); + console.log("currentTime: " + await latestTime()); + 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}) + ); + + console.log("\t\t Tx failed as expected"); + } else if (transactionAmount <= newIR) { + + console.log("\t\t Tx should succeed"); + + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei(transactionAmount.toString()), {from: account_investor1}); + + console.log("\t\t Tx succeeded"); + } + await revertToSnapshot(snapId); + console.log("\t\t Finished test number "+j); + }; + + await I_VolumeRestrictionTM.removeIndividualRestriction(account_investor1, {from: token_owner}); + console.log("\t\t Removed daily restriction"); + } + + }); + + }); + +}); diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 2614e6d5d..7f7933801 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -18,7 +18,7 @@ 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 VolumeRestrictionTransferManager = artifacts.require("./VolumeRestrictionTM"); const PercentageTransferManager = artifacts.require("./PercentageTransferManager"); const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); @@ -97,6 +97,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { let bytesSTO = encodeModuleCall(["uint256"], [holderCount]); let _details = "details holding for test"; + let _description = "some description"; let testRepeat = 20; // permission manager fuzz test @@ -181,7 +182,7 @@ contract("GeneralPermissionManager Fuzz", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -672,6 +673,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { account_investor4, new BN(web3.utils.toWei("2", "ether")), nextTime, + web3.utils.fromAscii(_details), { from: accounts[j] } ); @@ -694,6 +696,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { account_investor4, new BN(web3.utils.toWei("2", "ether")), nextTime, + web3.utils.fromAscii(_details), { from: accounts[j] } ) ); @@ -704,6 +707,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { account_investor4, new BN(web3.utils.toWei("2", "ether")), nextTime, + web3.utils.fromAscii(_details), { from: token_owner } ); @@ -719,102 +723,5 @@ contract("GeneralPermissionManager Fuzz", async (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, currentTime.add(new BN(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], web3.utils.fromAscii(_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, - web3.utils.fromAscii("TRANSFER_APPROVAL") - )) === true - ) { - await I_GeneralPermissionManager.changePermission( - accounts[j], - I_ManualApprovalTransferManager.address, - web3.utils.fromAscii("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, web3.utils.fromAscii(randomPerms), true, { - from: token_owner - }); - - if (randomPerms === "TRANSFER_APPROVAL") { - console.log("Test number " + i + " with account " + j + " and perm TRANSFER_APPROVAL " + " should pass"); - let nextTime = new BN(await latestTime()).add(new BN(duration.days(1))); - await I_ManualApprovalTransferManager.addManualBlocking( - account_investor1, - account_investor2, - nextTime, - { - 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"); - let nextTime = new BN(await latestTime()).add(new BN(duration.days(1))); - await catchRevert( - I_ManualApprovalTransferManager.addManualBlocking( - account_investor1, - account_investor2, - nextTime, - { - from: accounts[j] - } - ) - ); - - nextTime = new BN(await latestTime()).add(new BN(duration.days(1))); - await I_ManualApprovalTransferManager.addManualBlocking( - account_investor1, - account_investor2, - nextTime, - { - 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); - } - }); }); }); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js new file mode 100644 index 000000000..b5aba3441 --- /dev/null +++ b/test/z_vesting_escrow_wallet.js @@ -0,0 +1,1221 @@ +import {deployGPMAndVerifyed, deployVestingEscrowWalletAndVerifyed, setUpPolymathNetwork} from "./helpers/createInstances"; +import latestTime from "./helpers/latestTime"; +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 GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); + +const Web3 = require('web3'); +const BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port + +contract('VestingEscrowWallet', accounts => { + + const CREATED = 0; + const STARTED = 1; + const COMPLETED = 2; + + // Accounts Variable declaration + let account_polymath; + let token_owner; + let wallet_admin; + let account_beneficiary1; + let account_beneficiary2; + let account_beneficiary3; + + let beneficiaries; + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_VestingEscrowWalletFactory; + let I_GeneralPermissionManager; + let I_VestingEscrowWallet; + 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"; + const delegateDetails = web3.utils.toHex("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 = new BN(web3.utils.toWei("250")); + + let currentTime; + const address_zero = "0x0000000000000000000000000000000000000000"; + + before(async () => { + currentTime = new BN(await latestTime()); + // Accounts setup + account_polymath = accounts[0]; + token_owner = accounts[1]; + wallet_admin = accounts[2]; + + account_beneficiary1 = accounts[6]; + account_beneficiary2 = accounts[7]; + account_beneficiary3 = accounts[8]; + + beneficiaries = [ + account_beneficiary1, + account_beneficiary2, + account_beneficiary3 + ]; + + // 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 GeneralDelegateManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); + + // STEP 3: Deploy the VestingEscrowWallet + [I_VestingEscrowWalletFactory] = await deployVestingEscrowWalletAndVerifyed(account_polymath, I_MRProxied, 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} + GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} + + I_VestingEscrowWalletFactory: ${I_VestingEscrowWalletFactory.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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toString(), 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 = await 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", new BN(0), new BN(0), { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toString(), 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 = await GeneralPermissionManager.at(tx.logs[2].args._module); + }); + + 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 }); + + assert.equal(tx.logs[2].args._types[0].toString(), 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 = await 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, + currentTime, + currentTime, + currentTime.add(new BN(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.toHex(web3.utils.toWei('1', 'ether')), { from: token_owner }); + + assert.equal( + (await I_SecurityToken.balanceOf(token_owner)).toString(), + 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], + [currentTime, currentTime, currentTime, currentTime], + [currentTime, currentTime, currentTime, currentTime], + [currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(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); + }); + + it("Should provide the permission", async() => { + let tx = await I_GeneralPermissionManager.changePermission( + wallet_admin, + I_VestingEscrowWallet.address, + web3.utils.toHex("ADMIN"), + true, + {from: token_owner} + ); + 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"); + 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 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." + ); + }); + + }); + + 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(address_zero, {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: token_owner}) + ); + }); + + 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 }); + const tx = await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); + + assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens, numberOfTokens); + + let balance = await I_SecurityToken.balanceOf.call(I_VestingEscrowWallet.address); + assert.equal(balance.toString(), numberOfTokens); + }); + + it("Should not be able to withdraw tokens to a treasury -- fail because of permissions check", async () => { + await catchRevert( + 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(numberOfTokens, {from: wallet_admin}); + + assert.equal(tx.logs[0].args._numberOfTokens, numberOfTokens); + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + assert.equal(unassignedTokens, 0); + + let balance = await I_SecurityToken.balanceOf.call(I_VestingEscrowWallet.address); + assert.equal(balance.toString(), 0); + }); + + it("Should not be able to push available tokens -- fail because of permissions check", async () => { + currentTime = new BN(await latestTime()); + let templateName = web3.utils.toHex("template-01"); + let numberOfTokens = 75000; + let duration = new BN(durationUtil.seconds(30)); + let frequency = new BN(durationUtil.seconds(10)); + let timeShift = new BN(durationUtil.seconds(100)); + let startTime = currentTime.add(timeShift); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + await increaseTime(durationUtil.seconds(110)); + + await catchRevert( + I_VestingEscrowWallet.pushAvailableTokens(account_beneficiary3, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to remove template -- fail because template is used", async () => { + await catchRevert( + I_VestingEscrowWallet.removeTemplate(web3.utils.toHex("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}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[0].args._numberOfTokens.toString(), numberOfTokens / 3); + + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toString(), numberOfTokens / 3); + + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); + }); + + it("Should fail to modify vesting schedule -- fail because schedule already started", async () => { + let templateName = web3.utils.toHex("template-01"); + let startTime = currentTime + 100; + await catchRevert( + 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}); + 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 () => { + await catchRevert( + I_VestingEscrowWallet.modifySchedule(account_beneficiary3, web3.utils.toHex("template-01"), currentTime - 1000, {from: wallet_admin}) + ); + }); + + it("Should withdraw available tokens to the beneficiary address", async () => { + currentTime = new BN(await latestTime()); + let templateName = web3.utils.toHex("template-02"); + let numberOfTokens = 33000; + let duration = new BN(durationUtil.seconds(30)); + let frequency = new BN(durationUtil.seconds(10)); + let timeShift = new BN(durationUtil.seconds(100)); + let startTime = currentTime.add(timeShift); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.addSchedule(account_beneficiary3, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + await increaseTime(durationUtil.seconds(130)); + + 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.toString(), numberOfTokens); + + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toString(), numberOfTokens); + + 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}); + }); + + it("Should withdraw available tokens 2 times by 3 schedules to the beneficiary address", async () => { + currentTime = new BN(await latestTime()); + let schedules = [ + { + templateName: web3.utils.toHex("template-1-01"), + numberOfTokens: new BN(100000), + duration: new BN(durationUtil.minutes(4)), + frequency: new BN(durationUtil.minutes(1)) + }, + { + templateName: web3.utils.toHex("template-1-02"), + numberOfTokens: new BN(30000), + duration: new BN(durationUtil.minutes(6)), + frequency: new BN(durationUtil.minutes(1)) + }, + { + templateName: web3.utils.toHex("template-1-03"), + numberOfTokens: new BN(2000), + duration: new BN(durationUtil.minutes(10)), + frequency: new BN(durationUtil.minutes(1)) + } + ]; + + let timeShift = new BN(durationUtil.seconds(100)); + let totalNumberOfTokens = getTotalNumberOfTokens(schedules); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + 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; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + let startTime = currentTime.add(timeShift); + 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)); + + let numberOfTokens = 100000 + (30000 / 6 * stepCount) + (2000 / 10 * stepCount); + 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.toString(), 100000); + assert.equal(tx.logs[1].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[1].args._numberOfTokens.toString(), 30000 / 6 * stepCount); + assert.equal(tx.logs[2].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[2].args._numberOfTokens.toString(), 2000 / 10 * stepCount); + + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toString(), numberOfTokens); + + stepCount = 4; + await increaseTime(durationUtil.minutes(stepCount) + durationUtil.seconds(100)); + + 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.toString(), 2000 / 10 * stepCount); + + balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toString(), totalNumberOfTokens); + + 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}); + } + }); + + }); + + describe("Adding, modifying and revoking vesting schedule", async () => { + let template_2_01 = web3.utils.toHex("template-2-01"); + + let schedules = [ + { + templateName: web3.utils.toHex("template-2-01"), + numberOfTokens: 100000, + duration: new BN(durationUtil.years(4)), + frequency: new BN(durationUtil.years(1)), + // startTime: currentTime.add(new BN(durationUtil.days(1))) + }, + { + templateName: web3.utils.toHex("template-2-02"), + numberOfTokens: 30000, + duration: new BN(durationUtil.weeks(6)), + frequency: new BN(durationUtil.weeks(1)), + // startTime: currentTime.add(new BN(durationUtil.days(2))) + }, + { + templateName: web3.utils.toHex("template-2-03"), + numberOfTokens: 2000, + duration: new BN(durationUtil.days(10)), + frequency: new BN(durationUtil.days(2)), + // startTime: currentTime.add(new BN(durationUtil.days(3))) + } + ]; + + it("Should fail to add vesting schedule to the beneficiary address -- fail because address in invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.addSchedule(address_zero, template_2_01, 100000, 4, 1, currentTime.add(new BN(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, template_2_01, 100000, 4, 1, currentTime.add(new BN(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, template_2_01, 0, 4, 1, currentTime.add(new BN(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, template_2_01, 100000, 4, 3, currentTime.add(new BN(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, template_2_01, 5, 4, 1, currentTime.add(new BN(durationUtil.days(1))), {from: wallet_admin}) + ); + }); + + it("Should fail to get vesting schedule -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.getSchedule(address_zero, template_2_01) + ); + }); + + it("Should fail to get vesting schedule -- fail because schedule not found", async () => { + + await catchRevert( + I_VestingEscrowWallet.getSchedule(account_beneficiary1, template_2_01) + ); + }); + + it("Should fail to get count of vesting schedule -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.getScheduleCount(address_zero) + ); + }); + + 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; + let startTime = currentTime.add(new BN(durationUtil.days(1))); + currentTime = new BN(await latestTime()); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); + await catchRevert( + I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: account_beneficiary1}) + ); + 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 () => { + currentTime = new BN(await latestTime()); + let templateName = schedules[0].templateName; + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = currentTime.add(new BN(durationUtil.days(1))); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, {from: token_owner}); + await I_VestingEscrowWallet.depositTokens(numberOfTokens, {from: token_owner}); + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary1, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + + 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]), web3.utils.hexToUtf8(templateName)); + }); + + it("Should add vesting schedule without depositing to the beneficiary address", async () => { + currentTime = new BN(await latestTime()); + let templateName = web3.utils.toHex("template-2-01-2"); + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = currentTime.add(new BN(durationUtil.days(1))); + 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: token_owner}); + + 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); + + 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.removeTemplate(templateName, {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 () => { + currentTime = new BN(await latestTime()); + let templateName = web3.utils.toHex("template-2-03"); + let startTime = currentTime.add(new BN(durationUtil.days(1))); + await catchRevert( + 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, web3.utils.toHex("template-2-01"), currentTime.add(new BN(100)), {from: account_beneficiary1}) + ); + }); + + it("Should modify vesting schedule for the beneficiary's address", async () => { + currentTime = new BN(await latestTime()); + let templateName = web3.utils.toHex("template-2-01"); + let numberOfTokens = schedules[0].numberOfTokens; + let duration = schedules[0].duration; + let frequency = schedules[0].frequency; + let startTime = currentTime.add(new BN(durationUtil.days(2))); + const tx = await I_VestingEscrowWallet.modifySchedule(account_beneficiary1, templateName, startTime, {from: wallet_admin}); + + checkScheduleLog(tx.logs[0], account_beneficiary1, templateName, startTime); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount.toString(), 1); + + let schedule = await I_VestingEscrowWallet.getSchedule.call(account_beneficiary1, templateName); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); + }); + + it("Should not be able to revoke schedule -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, web3.utils.toHex("template-2-01"), {from: account_beneficiary1}) + ); + }); + + it("Should revoke vesting schedule from the beneficiary address", async () => { + let templateName = web3.utils.toHex("template-2-01"); + const tx = await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {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), web3.utils.hexToUtf8(templateName)); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary1); + assert.equal(scheduleCount, 0); + + await I_VestingEscrowWallet.removeTemplate(templateName, {from: wallet_admin}) + }); + + it("Should fail to revoke vesting schedule -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedule(address_zero, web3.utils.toHex("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, web3.utils.toHex("template-2-02"), {from: wallet_admin}) + ); + }); + + it("Should fail to revoke vesting schedules -- fail because address is invalid", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeAllSchedules(address_zero, {from: wallet_admin}) + ); + }); + + it("Should add 3 vesting schedules to the beneficiary address", async () => { + currentTime = new BN(await latestTime()); + let startTimes = [ + currentTime.add(new BN(durationUtil.days(1))), + currentTime.add(new BN(durationUtil.days(2))), + currentTime.add(new BN(durationUtil.days(3))) + ]; + let totalNumberOfTokens = getTotalNumberOfTokens(schedules); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + 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; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + let startTime = startTimes[i]; + const tx = await I_VestingEscrowWallet.addSchedule(account_beneficiary2, templateName, numberOfTokens, duration, frequency, startTime, {from: wallet_admin}); + + 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, templateName); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, CREATED); + } + }); + + it("Should not be able to revoke schedules -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary1, {from: account_beneficiary1}) + ); + }); + + 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}); + 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), web3.utils.hexToUtf8(templateName)); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); + assert.equal(scheduleCount, 2); + }); + + it("Should revoke 2 vesting schedules from the beneficiary address", async () => { + const tx = await I_VestingEscrowWallet.revokeAllSchedules(account_beneficiary2, {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); + + let scheduleCount = await I_VestingEscrowWallet.getScheduleCount.call(account_beneficiary2); + assert.equal(scheduleCount, 0); + }); + + it("Should push available tokens during revoking vesting schedule", async () => { + currentTime = new BN(await latestTime()); + let schedules = [ + { + templateName: web3.utils.toHex("template-3-01"), + numberOfTokens: new BN(100000), + duration: new BN(durationUtil.minutes(4)), + frequency: new BN(durationUtil.minutes(1)) + }, + { + templateName: web3.utils.toHex("template-3-02"), + numberOfTokens: new BN(30000), + duration: new BN(durationUtil.minutes(6)), + frequency: new BN(durationUtil.minutes(1)) + }, + { + templateName: web3.utils.toHex("template-3-03"), + numberOfTokens: new BN(2000), + duration: new BN(durationUtil.minutes(10)), + frequency: new BN(durationUtil.minutes(1)) + } + ]; + + let totalNumberOfTokens = getTotalNumberOfTokens(schedules); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + 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; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + let startTime = currentTime.add(new BN(100)); + 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, web3.utils.toHex("template-3-01"), {from: wallet_admin}); + assert.equal(tx.logs[0].args._beneficiary, account_beneficiary3); + assert.equal(tx.logs[0].args._numberOfTokens.toString(), 100000 / 4 * stepCount); + + let balance = await I_SecurityToken.balanceOf.call(account_beneficiary3); + assert.equal(balance.toString(), 100000 / 4 * stepCount); + + stepCount = 7; + await increaseTime(durationUtil.minutes(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.toString(), 2000); + assert.equal(tx2.logs[1].args._beneficiary, account_beneficiary3); + assert.equal(tx2.logs[1].args._numberOfTokens.toString(), 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.toString(), totalNumberOfTokens - 100000 / 4); + + await I_SecurityToken.transfer(token_owner, balance, {from: account_beneficiary3}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); + }); + + }); + + describe("Adding, using and removing templates", async () => { + let schedules = [ + { + templateName: web3.utils.toHex("template-4-01"), + numberOfTokens: 100000, + duration: new BN(durationUtil.years(4)), + frequency: new BN(durationUtil.years(1)), + // startTime: currentTime.add(new BN(durationUtil.days(1))) + }, + { + templateName: web3.utils.toHex("template-4-02"), + numberOfTokens: 30000, + duration: new BN(durationUtil.weeks(6)), + frequency: new BN(durationUtil.weeks(1)), + // startTime: currentTime.add(new BN(durationUtil.days(2))) + }, + { + templateName: web3.utils.toHex("template-4-03"), + numberOfTokens: 2000, + duration: new BN(durationUtil.days(10)), + frequency: new BN(durationUtil.days(2)), + // startTime: currentTime.add(new BN(durationUtil.days(3))) + } + ]; + + it("Should not be able to add template -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.addTemplate(web3.utils.toHex("template-4-01"), 25000, 4, 1, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to add template -- fail because of invalid name", async () => { + await catchRevert( + I_VestingEscrowWallet.addTemplate(web3.utils.toHex(""), 25000, 4, 1, {from: wallet_admin}) + ); + }); + + 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; + let duration = schedules[i].duration; + let frequency = schedules[i].frequency; + const tx = await I_VestingEscrowWallet.addTemplate(templateName, numberOfTokens, duration, frequency, {from: wallet_admin}); + + assert.equal(web3.utils.hexToUtf8(tx.logs[0].args._name), web3.utils.hexToUtf8(templateName)); + assert.equal(tx.logs[0].args._numberOfTokens.toString(), numberOfTokens); + assert.equal(tx.logs[0].args._duration.toString(), duration); + assert.equal(tx.logs[0].args._frequency.toString(), 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]), web3.utils.hexToUtf8(schedules[i].templateName)); + } + }); + + it("Should not be able to add template -- fail because template already exists", async () => { + await catchRevert( + I_VestingEscrowWallet.addTemplate(web3.utils.toHex("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(web3.utils.toHex("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(web3.utils.toHex("template-444-02"), {from: wallet_admin}) + ); + }); + + it("Should remove template", async () => { + const tx = await I_VestingEscrowWallet.removeTemplate(web3.utils.toHex("template-4-02"), {from: wallet_admin}); + + 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 () => { + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, web3.utils.toHex("template-4-02"), currentTime, {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, web3.utils.toHex("template-4-01"), currentTime, {from: account_beneficiary1}) + ); + }); + + it("Should not be able to add vesting schedule from template -- fail because template not found", async () => { + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, web3.utils.toHex("template-777"), currentTime + 100, {from: wallet_admin}) + ); + }); + + 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 = currentTime.add(new BN(durationUtil.days(3))); + currentTime = new BN(await latestTime()); + await I_SecurityToken.approve(I_VestingEscrowWallet.address, numberOfTokens, { from: token_owner }); + 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); + + 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); + + await I_VestingEscrowWallet.revokeSchedule(account_beneficiary1, templateName, {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 () => { + let templateName = schedules[2].templateName; + await catchRevert( + I_VestingEscrowWallet.addScheduleFromTemplate(account_beneficiary1, templateName, currentTime.add(new BN(100)), {from: wallet_admin}) + ); + }); + + it("Should fail to remove template", async () => { + await catchRevert( + I_VestingEscrowWallet.removeTemplate(web3.utils.toHex("template-4-02"), {from: wallet_admin}) + ); + }); + + it("Should remove 2 Templates", async () => { + let templateCount = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); + + await I_VestingEscrowWallet.removeTemplate(web3.utils.toHex("template-4-01"), {from: wallet_admin}); + await I_VestingEscrowWallet.removeTemplate(web3.utils.toHex("template-4-03"), {from: wallet_admin}); + + let templateCountAfterRemoving = await I_VestingEscrowWallet.getTemplateCount.call({from: wallet_admin}); + assert.equal(templateCount - templateCountAfterRemoving, 2); + }); + + }); + + describe("Tests for multi operations", async () => { + + let templateNames = [web3.utils.toHex("template-5-01"), web3.utils.toHex("template-5-02"), web3.utils.toHex("template-5-03")]; + + it("Should not be able to add schedules to the beneficiaries -- fail because of permissions check", async () => { + currentTime = new BN(await latestTime()); + let startTime = currentTime.add(new BN(100)); + let startTimes = [startTime, startTime, startTime]; + await catchRevert( + I_VestingEscrowWallet.addScheduleMulti(beneficiaries, templateNames, [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 startTime = currentTime.add(new BN(100)); + let startTimes = [startTime, startTime, startTime]; + let totalNumberOfTokens = 60000; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + 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}) + ); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); + }); + + it("Should add schedules for 3 beneficiaries", async () => { + let numberOfTokens = [15000, 15000, 15000]; + let durations = [new BN(durationUtil.seconds(50)), new BN(durationUtil.seconds(50)), new BN(durationUtil.seconds(50))]; + let frequencies = [new BN(durationUtil.seconds(10)), new BN(durationUtil.seconds(10)), new BN(durationUtil.seconds(10))]; + let timeShift = new BN(durationUtil.seconds(100)); + let startTimes = [currentTime.add(timeShift), currentTime.add(timeShift), currentTime.add(timeShift)]; + + let totalNumberOfTokens = 60000; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + 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 templateName = templateNames[i]; + let beneficiary = beneficiaries[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, templateName); + checkSchedule(schedule, numberOfTokens[i], durations[i], frequencies[i], startTimes[i], CREATED); + } + }); + + it("Should not be able modify vesting schedule for 3 beneficiary's addresses -- fail because of arrays sizes mismatch", async () => { + let timeShift = new BN(durationUtil.seconds(100)); + let startTimes = [currentTime.add(timeShift), currentTime.add(timeShift), currentTime.add(timeShift)]; + + await catchRevert( + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, [web3.utils.toHex("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 timeShift = new BN(durationUtil.seconds(100)); + let startTimes = [currentTime.add(timeShift), currentTime.add(timeShift), currentTime.add(timeShift)]; + + await catchRevert( + I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, templateNames, startTimes, {from: account_beneficiary1}) + ); + }); + + it("Should modify vesting schedule for 3 beneficiary's addresses", async () => { + let numberOfTokens = [new BN(15000), new BN(15000), new BN(15000)]; + let durations = [new BN(durationUtil.seconds(50)), new BN(durationUtil.seconds(50)), new BN(durationUtil.seconds(50))]; + let frequencies = [new BN(durationUtil.seconds(10)), new BN(durationUtil.seconds(10)), new BN(durationUtil.seconds(10))]; + let timeShift = new BN(durationUtil.seconds(100)); + let startTimes = [currentTime.add(timeShift), currentTime.add(timeShift), currentTime.add(timeShift)]; + + const tx = await I_VestingEscrowWallet.modifyScheduleMulti(beneficiaries, templateNames, startTimes, {from: wallet_admin}); + await increaseTime(110); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[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, templateNames[i]); + checkSchedule(schedule, numberOfTokens[i], durations[i], frequencies[i], startTimes[i], STARTED); + } + }); + + it("Should not be able to send available tokens to the beneficiaries addresses -- fail because of array size", async () => { + await catchRevert( + I_VestingEscrowWallet.pushAvailableTokensMulti(new BN(0), new BN(3), {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(new BN(0), new BN(2), {from: account_beneficiary1}) + ); + }); + + it("Should send available tokens to the beneficiaries addresses", async () => { + const tx = await I_VestingEscrowWallet.pushAvailableTokensMulti(0, 2, {from: wallet_admin}); + + for (let i = 0; i < beneficiaries.length; i++) { + let log = tx.logs[i]; + let beneficiary = beneficiaries[i]; + assert.equal(log.args._numberOfTokens.toString(), 3000); + + let balance = await I_SecurityToken.balanceOf.call(beneficiary); + assert.equal(balance.toString(), 3000); + + 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}); + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); + } + }); + + it("Should not be able to add schedules from template to the beneficiaries -- fail because of permissions check", async () => { + let templateName = web3.utils.toHex("template-6-01"); + let numberOfTokens = 18000; + let duration = durationUtil.weeks(3); + let frequency = durationUtil.weeks(1); + let templateNames = [templateName, templateName, templateName]; + let startTime = currentTime.add(new BN(durationUtil.seconds(100))); + let startTimes = [startTime, startTime, startTime]; + + let totalNumberOfTokens = numberOfTokens * 3; + await I_SecurityToken.approve(I_VestingEscrowWallet.address, totalNumberOfTokens, {from: token_owner}); + 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, templateNames, startTimes, {from: account_beneficiary1}) + ); + }); + + it("Should add schedules from template for 3 beneficiaries", async () => { + currentTime = new BN(await latestTime()); + let templateName = web3.utils.toHex("template-6-01"); + let numberOfTokens = 18000; + let duration = durationUtil.weeks(3); + let frequency = durationUtil.weeks(1); + let templateNames = [templateName, templateName, templateName]; + let startTime = currentTime.add(new BN(durationUtil.seconds(100))); + let startTimes = [startTime, startTime, startTime]; + + 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 schedule = await I_VestingEscrowWallet.getSchedule.call(beneficiary, templateName); + checkSchedule(schedule, numberOfTokens, duration, frequency, startTimes[i], CREATED); + } + }); + + it("Should not be able to revoke schedules of the beneficiaries -- fail because of permissions check", async () => { + await catchRevert( + I_VestingEscrowWallet.revokeSchedulesMulti(beneficiaries, {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}); + + 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); + } + + let unassignedTokens = await I_VestingEscrowWallet.unassignedTokens.call(); + await I_VestingEscrowWallet.sendToTreasury(unassignedTokens, {from: wallet_admin}); + }); + + }); + +}); + +function checkTemplateLog(log, templateName, numberOfTokens, duration, frequency) { + assert.equal(web3.utils.hexToUtf8(log.args._name), web3.utils.hexToUtf8(templateName)); + assert.equal(log.args._numberOfTokens.toString(), numberOfTokens); + assert.equal(log.args._duration.toString(), duration); + assert.equal(log.args._frequency.toString(), frequency); +} + +function checkScheduleLog(log, beneficiary, templateName, startTime) { + assert.equal(log.args._beneficiary, beneficiary); + assert.equal(web3.utils.hexToUtf8(log.args._templateName), web3.utils.hexToUtf8(templateName)); + assert.equal(log.args._startTime.toString(), startTime); +} + +function checkSchedule(schedule, numberOfTokens, duration, frequency, startTime, state) { + assert.equal(schedule[0].toString(), numberOfTokens); + assert.equal(schedule[1].toString(), duration); + assert.equal(schedule[2].toString(), frequency); + assert.equal(schedule[3].toString(), startTime); + assert.equal(schedule[5].toString(), state); +} + +function getTotalNumberOfTokens(schedules) { + let numberOfTokens = new BN(0); + for (let i = 0; i < schedules.length; i++) { + numberOfTokens = numberOfTokens.add(new BN(schedules[i].numberOfTokens)); + } + return numberOfTokens; +} From 71631d7481ebfa167280968db15aa5fda48153e9 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 29 Jan 2019 14:37:08 -0400 Subject: [PATCH 085/119] Small update to setSecurityToken --- contracts/datastore/DataStore.sol | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 3bef0b6a0..6ab6b4d47 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -13,11 +13,13 @@ contract DataStore is DataStoreStorage, IDataStore { //Whenver an element is deleted from an Array, last element of that array is moved to the index of deleted element. //Delegate with MANAGEDATA permission can modify data. + event SecurityTokenChanged(address indexed _oldSecurityToken, address indexed _newSecurityToken); + modifier onlyAuthorized() { bool isOwner = msg.sender == IOwnable(address(securityToken)).owner(); - require(isOwner || - securityToken.isModule(msg.sender, DATA_KEY) || - securityToken.checkPermission(msg.sender, address(this), MANAGEDATA), + require(isOwner || + securityToken.isModule(msg.sender, DATA_KEY) || + securityToken.checkPermission(msg.sender, address(this), MANAGEDATA), "Unauthorized" ); _; @@ -43,11 +45,10 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _securityToken address of the security token */ function setSecurityToken(address _securityToken) external onlyOwner { - if(address(securityToken) != address(0)) { - require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); - } + require(_securityToken != address(0), "Invalid address"); + emit SecurityTokenChanged(securityToken, _securityToken); securityToken = ISecurityToken(_securityToken); - } + } /** * @dev Stores a uint256 data against a key From 81ff0dcd9e1ac8a93a9a8267ec624d0a70ef2de7 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 29 Jan 2019 14:53:25 -0400 Subject: [PATCH 086/119] Fix --- contracts/datastore/DataStore.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 6ab6b4d47..3c68aac97 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -46,7 +46,7 @@ contract DataStore is DataStoreStorage, IDataStore { */ function setSecurityToken(address _securityToken) external onlyOwner { require(_securityToken != address(0), "Invalid address"); - emit SecurityTokenChanged(securityToken, _securityToken); + emit SecurityTokenChanged(address(securityToken), _securityToken); securityToken = ISecurityToken(_securityToken); } From 07fc1f2ed605ded1806bd8260560b30088ae0a71 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 30 Jan 2019 16:38:40 +0400 Subject: [PATCH 087/119] Datastore (#522) * Test cases for data store * Rebase conflicts resolved * wip ds proxy * DS deployment * Fixed create instance helper * tests fixed * Added KYC TM module * Added array operation * Added features * Added batch functions * Removed multi delete * Removed overloaded external functions * Added test cases * Code cleanup and comments * Added test cases for security token * Added more test cases for data store * minor fixes * Small update to setSecurityToken * Fix --- contracts/datastore/DataStore.sol | 363 ++++++++++++++ contracts/datastore/DataStoreFactory.sol | 18 + contracts/datastore/DataStoreStorage.sol | 21 + contracts/interfaces/IDataStore.sol | 128 +++++ contracts/interfaces/ISecurityToken.sol | 19 + .../TransferManager/KYCTransferManager.sol | 99 ++++ .../KYCTransferManagerFactory.sol | 63 +++ contracts/proxy/DataStoreProxy.sol | 29 ++ contracts/tokens/STFactory.sol | 6 +- contracts/tokens/SecurityToken.sol | 24 +- migrations/2_deploy_contracts.js | 12 +- test/helpers/createInstances.js | 6 +- test/n_security_token_registry.js | 7 +- test/o_security_token.js | 17 +- test/u_module_registry_proxy.js | 6 +- test/za_datastore.js | 468 ++++++++++++++++++ 16 files changed, 1279 insertions(+), 7 deletions(-) create mode 100644 contracts/datastore/DataStore.sol create mode 100644 contracts/datastore/DataStoreFactory.sol create mode 100644 contracts/datastore/DataStoreStorage.sol create mode 100644 contracts/interfaces/IDataStore.sol create mode 100644 contracts/modules/Experimental/TransferManager/KYCTransferManager.sol create mode 100644 contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol create mode 100644 contracts/proxy/DataStoreProxy.sol create mode 100644 test/za_datastore.js diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol new file mode 100644 index 000000000..3c68aac97 --- /dev/null +++ b/contracts/datastore/DataStore.sol @@ -0,0 +1,363 @@ +pragma solidity ^0.5.0; + +import "../interfaces/ISecurityToken.sol"; +import "../interfaces/IOwnable.sol"; +import "../interfaces/IDataStore.sol"; +import "./DataStoreStorage.sol"; + +/** + * @title Data store contract that stores data for all the modules in a central contract. + */ +contract DataStore is DataStoreStorage, IDataStore { + //NB To modify a specific element of an array, First push a new element to the array and then delete the old element. + //Whenver an element is deleted from an Array, last element of that array is moved to the index of deleted element. + //Delegate with MANAGEDATA permission can modify data. + + event SecurityTokenChanged(address indexed _oldSecurityToken, address indexed _newSecurityToken); + + modifier onlyAuthorized() { + bool isOwner = msg.sender == IOwnable(address(securityToken)).owner(); + require(isOwner || + securityToken.isModule(msg.sender, DATA_KEY) || + securityToken.checkPermission(msg.sender, address(this), MANAGEDATA), + "Unauthorized" + ); + _; + } + + modifier validKey(bytes32 _key) { + require(_key != bytes32(0), "Missing key"); + _; + } + + modifier validArrayLength(uint256 _keyLength, uint256 _dataLength) { + require(_keyLength == _dataLength, "Array length mismatch"); + _; + } + + modifier onlyOwner() { + require(msg.sender == IOwnable(address(securityToken)).owner(), "Unauthorized"); + _; + } + + /** + * @dev Changes security token atatched to this data store + * @param _securityToken address of the security token + */ + function setSecurityToken(address _securityToken) external onlyOwner { + require(_securityToken != address(0), "Invalid address"); + emit SecurityTokenChanged(address(securityToken), _securityToken); + securityToken = ISecurityToken(_securityToken); + } + + /** + * @dev Stores a uint256 data against a key + * @param _key Unique key to identify the data + * @param _data Data to be stored against the key + */ + function setUint256(bytes32 _key, uint256 _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setAddress(bytes32 _key, address _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setString(bytes32 _key, string calldata _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setBytes(bytes32 _key, bytes calldata _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setBool(bytes32 _key, bool _data) external onlyAuthorized { + _setData(_key, _data); + } + + /** + * @dev Stores a uint256 array against a key + * @param _key Unique key to identify the array + * @param _data Array to be stored against the key + */ + function setUint256Array(bytes32 _key, uint256[] calldata _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setBytes32Array(bytes32 _key, bytes32[] calldata _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setAddressArray(bytes32 _key, address[] calldata _data) external onlyAuthorized { + _setData(_key, _data); + } + + function setBoolArray(bytes32 _key, bool[] calldata _data) external onlyAuthorized { + _setData(_key, _data); + } + + /** + * @dev Inserts a uint256 element to the array identified by the key + * @param _key Unique key to identify the array + * @param _data Element to push into the array + */ + function insertUint256(bytes32 _key, uint256 _data) external onlyAuthorized { + _insertData(_key, _data); + } + + function insertBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { + _insertData(_key, _data); + } + + function insertAddress(bytes32 _key, address _data) external onlyAuthorized { + _insertData(_key, _data); + } + + function insertBool(bytes32 _key, bool _data) external onlyAuthorized { + _insertData(_key, _data); + } + + /** + * @dev Deletes an element from the array identified by the key. + * When an element is deleted from an Array, last element of that array is moved to the index of deleted element. + * @param _key Unique key to identify the array + * @param _index Index of the element to delete + */ + function deleteUint256(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteUint(_key, _index); + } + + function deleteBytes32(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteBytes32(_key, _index); + } + + function deleteAddress(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteAddress(_key, _index); + } + + function deleteBool(bytes32 _key, uint256 _index) external onlyAuthorized { + _deleteBool(_key, _index); + } + + /** + * @dev Stores multiple uint256 data against respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be stored against the respective keys + */ + function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); + } + } + + function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); + } + } + + function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); + } + } + + function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _setData(_keys[i], _data[i]); + } + } + + /** + * @dev Inserts multiple uint256 elements to the array identified by the respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be inserted in arrays of the respective keys + */ + function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + for (uint256 i = 0; i < _keys.length; i++) { + _insertData(_keys[i], _data[i]); + } + } + + function getUint256(bytes32 _key) external view returns(uint256) { + return uintData[_key]; + } + + function getBytes32(bytes32 _key) external view returns(bytes32) { + return bytes32Data[_key]; + } + + function getAddress(bytes32 _key) external view returns(address) { + return addressData[_key]; + } + + function getString(bytes32 _key) external view returns(string memory) { + return stringData[_key]; + } + + function getBytes(bytes32 _key) external view returns(bytes memory) { + return bytesData[_key]; + } + + function getBool(bytes32 _key) external view returns(bool) { + return boolData[_key]; + } + + function getUint256Array(bytes32 _key) external view returns(uint256[] memory) { + return uintArrayData[_key]; + } + + function getBytes32Array(bytes32 _key) external view returns(bytes32[] memory) { + return bytes32ArrayData[_key]; + } + + function getAddressArray(bytes32 _key) external view returns(address[] memory) { + return addressArrayData[_key]; + } + + function getBoolArray(bytes32 _key) external view returns(bool[] memory) { + return boolArrayData[_key]; + } + + function getUint256ArrayLength(bytes32 _key) external view returns(uint256) { + return uintArrayData[_key].length; + } + + function getBytes32ArrayLength(bytes32 _key) external view returns(uint256) { + return bytes32ArrayData[_key].length; + } + + function getAddressArrayLength(bytes32 _key) external view returns(uint256) { + return addressArrayData[_key].length; + } + + function getBoolArrayLength(bytes32 _key) external view returns(uint256) { + return boolArrayData[_key].length; + } + + function getUint256ArrayElement(bytes32 _key, uint256 _index) external view returns(uint256) { + return uintArrayData[_key][_index]; + } + + function getBytes32ArrayElement(bytes32 _key, uint256 _index) external view returns(bytes32) { + return bytes32ArrayData[_key][_index]; + } + + function getAddressArrayElement(bytes32 _key, uint256 _index) external view returns(address) { + return addressArrayData[_key][_index]; + } + + function getBoolArrayElement(bytes32 _key, uint256 _index) external view returns(bool) { + return boolArrayData[_key][_index]; + } + + function _setData(bytes32 _key, uint256 _data) internal validKey(_key) { + uintData[_key] = _data; + } + + function _setData(bytes32 _key, bytes32 _data) internal validKey(_key) { + bytes32Data[_key] = _data; + } + + function _setData(bytes32 _key, address _data) internal validKey(_key) { + addressData[_key] = _data; + } + + function _setData(bytes32 _key, string memory _data) internal validKey(_key) { + stringData[_key] = _data; + } + + function _setData(bytes32 _key, bytes memory _data) internal validKey(_key) { + bytesData[_key] = _data; + } + + function _setData(bytes32 _key, bool _data) internal validKey(_key) { + boolData[_key] = _data; + } + + function _setData(bytes32 _key, uint256[] memory _data) internal validKey(_key) { + uintArrayData[_key] = _data; + } + + function _setData(bytes32 _key, bytes32[] memory _data) internal validKey(_key) { + bytes32ArrayData[_key] = _data; + } + + function _setData(bytes32 _key, address[] memory _data) internal validKey(_key) { + addressArrayData[_key] = _data; + } + + function _setData(bytes32 _key, bool[] memory _data) internal validKey(_key) { + boolArrayData[_key] = _data; + } + + function _insertData(bytes32 _key, uint256 _data) internal validKey(_key) { + uintArrayData[_key].push(_data); + } + + function _insertData(bytes32 _key, bytes32 _data) internal validKey(_key) { + bytes32ArrayData[_key].push(_data); + } + + function _insertData(bytes32 _key, address _data) internal validKey(_key) { + addressArrayData[_key].push(_data); + } + + function _insertData(bytes32 _key, bool _data) internal validKey(_key) { + boolArrayData[_key].push(_data); + } + + function _deleteUint(bytes32 _key, uint256 _index) internal validKey(_key) { + require(uintArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(uintArrayData[_key].length - 1 != _index) { + uintArrayData[_key][_index] = uintArrayData[_key][uintArrayData[_key].length - 1]; + } + uintArrayData[_key].length--; + } + + function _deleteBytes32(bytes32 _key, uint256 _index) internal validKey(_key) { + require(bytes32ArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(bytes32ArrayData[_key].length - 1 != _index) { + bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][bytes32ArrayData[_key].length - 1]; + } + bytes32ArrayData[_key].length--; + } + + function _deleteAddress(bytes32 _key, uint256 _index) internal validKey(_key) { + require(addressArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(addressArrayData[_key].length - 1 != _index) { + addressArrayData[_key][_index] = addressArrayData[_key][addressArrayData[_key].length - 1]; + } + addressArrayData[_key].length--; + } + + function _deleteBool(bytes32 _key, uint256 _index) internal validKey(_key) { + require(boolArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow + if(boolArrayData[_key].length - 1 != _index) { + boolArrayData[_key][_index] = boolArrayData[_key][boolArrayData[_key].length - 1]; + } + boolArrayData[_key].length--; + } +} diff --git a/contracts/datastore/DataStoreFactory.sol b/contracts/datastore/DataStoreFactory.sol new file mode 100644 index 000000000..f4a3cc6d2 --- /dev/null +++ b/contracts/datastore/DataStoreFactory.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.0; + +import "../proxy/DataStoreProxy.sol"; + +contract DataStoreFactory { + + address public implementation; + + constructor(address _implementation) public { + require(_implementation != address(0), "Address should not be 0x"); + implementation = _implementation; + } + + function generateDataStore(address _securityToken) public returns (address) { + DataStoreProxy dsProxy = new DataStoreProxy(_securityToken, implementation); + return address(dsProxy); + } +} diff --git a/contracts/datastore/DataStoreStorage.sol b/contracts/datastore/DataStoreStorage.sol new file mode 100644 index 000000000..9d724f070 --- /dev/null +++ b/contracts/datastore/DataStoreStorage.sol @@ -0,0 +1,21 @@ +pragma solidity ^0.5.0; + +import "../interfaces/ISecurityToken.sol"; + +contract DataStoreStorage { + ISecurityToken public securityToken; + + mapping (bytes32 => uint256) internal uintData; + mapping (bytes32 => bytes32) internal bytes32Data; + mapping (bytes32 => address) internal addressData; + mapping (bytes32 => string) internal stringData; + mapping (bytes32 => bytes) internal bytesData; + mapping (bytes32 => bool) internal boolData; + mapping (bytes32 => uint256[]) internal uintArrayData; + mapping (bytes32 => bytes32[]) internal bytes32ArrayData; + mapping (bytes32 => address[]) internal addressArrayData; + mapping (bytes32 => bool[]) internal boolArrayData; + + uint8 constant DATA_KEY = 6; + bytes32 public constant MANAGEDATA = "MANAGEDATA"; +} diff --git a/contracts/interfaces/IDataStore.sol b/contracts/interfaces/IDataStore.sol new file mode 100644 index 000000000..bb1aa5aa4 --- /dev/null +++ b/contracts/interfaces/IDataStore.sol @@ -0,0 +1,128 @@ +pragma solidity ^0.5.0; + +interface IDataStore { + /** + * @dev Changes security token atatched to this data store + * @param _securityToken address of the security token + */ + function setSecurityToken(address _securityToken) external; + + /** + * @dev Stores a uint256 data against a key + * @param _key Unique key to identify the data + * @param _data Data to be stored against the key + */ + function setUint256(bytes32 _key, uint256 _data) external; + + function setBytes32(bytes32 _key, bytes32 _data) external; + + function setAddress(bytes32 _key, address _data) external; + + function setString(bytes32 _key, string calldata _data) external; + + function setBytes(bytes32 _key, bytes calldata _data) external; + + function setBool(bytes32 _key, bool _data) external; + + /** + * @dev Stores a uint256 array against a key + * @param _key Unique key to identify the array + * @param _data Array to be stored against the key + */ + function setUint256Array(bytes32 _key, uint256[] calldata _data) external; + + function setBytes32Array(bytes32 _key, bytes32[] calldata _data) external ; + + function setAddressArray(bytes32 _key, address[] calldata _data) external; + + function setBoolArray(bytes32 _key, bool[] calldata _data) external; + + /** + * @dev Inserts a uint256 element to the array identified by the key + * @param _key Unique key to identify the array + * @param _data Element to push into the array + */ + function insertUint256(bytes32 _key, uint256 _data) external; + + function insertBytes32(bytes32 _key, bytes32 _data) external; + + function insertAddress(bytes32 _key, address _data) external; + + function insertBool(bytes32 _key, bool _data) external; + + /** + * @dev Deletes an element from the array identified by the key. + * When an element is deleted from an Array, last element of that array is moved to the index of deleted element. + * @param _key Unique key to identify the array + * @param _index Index of the element to delete + */ + function deleteUint256(bytes32 _key, uint256 _index) external; + + function deleteBytes32(bytes32 _key, uint256 _index) external; + + function deleteAddress(bytes32 _key, uint256 _index) external; + + function deleteBool(bytes32 _key, uint256 _index) external; + + /** + * @dev Stores multiple uint256 data against respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be stored against the respective keys + */ + function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external; + + function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external; + + function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external; + + function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external; + + /** + * @dev Inserts multiple uint256 elements to the array identified by the respective keys + * @param _keys Array of keys to identify the data + * @param _data Array of data to be inserted in arrays of the respective keys + */ + function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external; + + function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external; + + function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external; + + function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external; + + function getUint256(bytes32 _key) external view returns(uint256); + + function getBytes32(bytes32 _key) external view returns(bytes32); + + function getAddress(bytes32 _key) external view returns(address); + + function getString(bytes32 _key) external view returns(string memory); + + function getBytes(bytes32 _key) external view returns(bytes memory); + + function getBool(bytes32 _key) external view returns(bool); + + function getUint256Array(bytes32 _key) external view returns(uint256[] memory); + + function getBytes32Array(bytes32 _key) external view returns(bytes32[] memory); + + function getAddressArray(bytes32 _key) external view returns(address[] memory); + + function getBoolArray(bytes32 _key) external view returns(bool[] memory); + + function getUint256ArrayLength(bytes32 _key) external view returns(uint256); + + function getBytes32ArrayLength(bytes32 _key) external view returns(uint256); + + function getAddressArrayLength(bytes32 _key) external view returns(uint256); + + function getBoolArrayLength(bytes32 _key) external view returns(uint256); + + function getUint256ArrayElement(bytes32 _key, uint256 _index) external view returns(uint256); + + function getBytes32ArrayElement(bytes32 _key, uint256 _index) external view returns(bytes32); + + function getAddressArrayElement(bytes32 _key, uint256 _index) external view returns(address); + + function getBoolArrayElement(bytes32 _key, uint256 _index) external view returns(bool); +} diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index 3228d8740..c1671db53 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -27,6 +27,13 @@ interface ISecurityToken { */ function verifyTransfer(address _from, address _to, uint256 _value, bytes calldata _data) external returns(bool success); + /** + * @notice Checks if an address is a module of certain type + * @param _module Address to check + * @param _type type to check against + */ + function isModule(address _module, uint8 _type) external view returns(bool); + /** * @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) @@ -154,6 +161,18 @@ interface ISecurityToken { */ function currentCheckpointId() external view returns(uint256); + /** + * @notice Gets data store address + * @return data store address + */ + function dataStore() external view returns (address); + + /** + * @notice Allows owner to change data store + * @param _dataStore Address of the token data store + */ + function changeDataStore(address _dataStore) external; + /** * @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. diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol new file mode 100644 index 000000000..7a314220e --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -0,0 +1,99 @@ +pragma solidity ^0.5.0; + +import "../../TransferManager/TransferManager.sol"; +import "../../../interfaces/IDataStore.sol"; +import "../../../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module for core transfer validation functionality + */ +contract KYCTransferManager is TransferManager { + + using SafeMath for uint256; + + bytes32 public constant KYC_NUMBER = "KYC_NUMBER"; //We will standardize what key to use for what. + + bytes32 public constant KYC_PROVIDER = "KYC_PROVIDER"; + + bytes32 public constant KYC_ARRAY = "KYC_ARRAY"; + + /** + * @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); + } + + function verifyTransfer(address /*_from*/, address _to, uint256 /*_amount*/, bytes memory /* _data */, bool /* _isTransfer */) + public + returns (Result) + { + if (!paused && checkKYC(_to)) { + return Result.VALID; + } + return Result.NA; + } + + function modifyKYC( address _investor, bool _kycStatus) public withPerm(KYC_PROVIDER) { + _modifyKYC(_investor, _kycStatus); + } + + function _modifyKYC(address _investor, bool _kycStatus) internal { + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + bytes32 key = _getKYCKey(_investor); + uint256 kycNumber = dataStore.getUint256(key); //index in address array + 1 + uint256 kycTotal = dataStore.getAddressArrayLength(KYC_ARRAY); + if(_kycStatus) { + require(kycNumber == 0, "KYC exists"); + dataStore.setUint256(key, kycTotal + 1); + dataStore.insertAddress(KYC_ARRAY, _investor); + } else { + require(kycNumber != 0, "KYC does not exist"); + address lastAddress = dataStore.getAddressArrayElement(KYC_ARRAY, kycTotal - 1); + dataStore.deleteAddress(KYC_ARRAY, kycNumber - 1); + + //Corrects the index of last element as delete fucntions move last element to index. + dataStore.setUint256(_getKYCKey(lastAddress), kycNumber); + } + //Alternatively, we can just emit an event and not maintain the KYC array on chain. + //I am maintaining the array to showcase how it can be done in cases where it might be needed. + } + + /** + * @notice Return the permissions flag that are associated with general trnasfer manager + */ + function getPermissions() public view returns(bytes32[] memory) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = KYC_PROVIDER; + return allPermissions; + } + + function getKYCAddresses() public view returns(address[] memory) { + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + return dataStore.getAddressArray(KYC_ARRAY); + } + + function checkKYC(address _investor) public view returns (bool kyc) { + bytes32 key = _getKYCKey(_investor); + IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); + if (dataStore.getUint256(key) > 0) + kyc = true; + } + + function _getKYCKey(address _identity) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(KYC_NUMBER, _identity))); + } + +} diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol new file mode 100644 index 000000000..13c9bc5a2 --- /dev/null +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol @@ -0,0 +1,63 @@ +pragma solidity ^0.5.0; + +import "./KYCTransferManager.sol"; +import "./../../ModuleFactory.sol"; + + +contract KYCTransferManagerFactory is ModuleFactory { + + /** + * @notice Constructor + */ + constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "KYCTransferManager"; + title = "KYC Transfer Manager"; + description = "Manages KYC"; + 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 calldata /* _data */) external returns(address) { + address polyToken = _takeFee(); + KYCTransferManager kycTransferManager = new KYCTransferManager(msg.sender, polyToken); + /*solium-disable-next-line security/no-block-members*/ + emit GenerateModuleFromFactory(address(kycTransferManager), getName(), address(this), msg.sender, setupCost, now); + return address(kycTransferManager); + } + + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[] memory) { + 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 memory) { + /*solium-disable-next-line max-len*/ + return "pray it works"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[] memory) { + bytes32[] memory availableTags = new bytes32[](1); + availableTags[0] = "KYC"; + return availableTags; + } + +} diff --git a/contracts/proxy/DataStoreProxy.sol b/contracts/proxy/DataStoreProxy.sol new file mode 100644 index 000000000..b79f5579d --- /dev/null +++ b/contracts/proxy/DataStoreProxy.sol @@ -0,0 +1,29 @@ +pragma solidity ^0.5.0; + +import "./OwnedProxy.sol"; +import "../datastore/DataStoreStorage.sol"; + +/** + * @title DataStoreProxy Proxy + */ +contract DataStoreProxy is DataStoreStorage, OwnedProxy { + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _implementation representing the address of the new implementation to be set + */ + constructor( + address _securityToken, + address _implementation + ) + public + { + require(_implementation != address(0) && _securityToken != address(0), + "Address should not be 0x" + ); + securityToken = ISecurityToken(_securityToken); + __implementation = _implementation; + } + +} diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index 702d118f8..d00e7e192 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -2,15 +2,18 @@ pragma solidity ^0.5.0; import "./SecurityToken.sol"; import "../interfaces/ISTFactory.sol"; +import "../datastore/DataStoreFactory.sol"; /** * @title Proxy for deploying SecurityToken instances */ contract STFactory is ISTFactory { address public transferManagerFactory; + DataStoreFactory public dataStoreFactory; - constructor(address _transferManagerFactory) public { + constructor(address _transferManagerFactory, address _dataStoreFactory) public { transferManagerFactory = _transferManagerFactory; + dataStoreFactory = DataStoreFactory(_dataStoreFactory); } /** @@ -38,6 +41,7 @@ contract STFactory is ISTFactory { _polymathRegistry ); newSecurityToken.addModule(transferManagerFactory, "", 0, 0); + newSecurityToken.changeDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); newSecurityToken.transferOwnership(_issuer); return address(newSecurityToken); } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index ae0c26d21..7e7e14ba2 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -46,6 +46,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint8 constant MINT_KEY = 3; uint8 constant CHECKPOINT_KEY = 4; uint8 constant BURN_KEY = 5; + uint8 constant DATA_KEY = 6; uint256 public granularity; @@ -64,6 +65,9 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Address whitelisted by issuer as controller address public controller; + // Address of the data store used to store shared data + address public dataStore; + // Records added modules - module list should be order agnostic! mapping(uint8 => address[]) modules; @@ -207,7 +211,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater securityTokenVersion = SemanticVersion(2, 0, 0); } - /** + /** * @notice Attachs a module to the SecurityToken * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it * @dev to control restrictions on transfers. @@ -368,6 +372,15 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater granularity = _granularity; } + /** + * @notice Allows owner to change data store + * @param _dataStore Address of the token data store + */ + function changeDataStore(address _dataStore) external onlyOwner { + require(_dataStore != address(0), "Invalid address"); + dataStore = _dataStore; + } + /** * @notice Keeps track of the number of non-zero token holders * @param _from sender of transfer @@ -683,6 +696,15 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater return false; } + /** + * @notice Checks if an address is a module of certain type + * @param _module Address to check + * @param _type type to check against + */ + function isModule(address _module, uint8 _type) public view returns(bool) { + return _isModule(_module, _type); + } + function _checkAndBurn(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); _burn(_from, _value); diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 47e2ef484..d6bd8efcd 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -28,6 +28,8 @@ const MockOracle = artifacts.require("./MockOracle.sol"); const TokenLib = artifacts.require("./TokenLib.sol"); const SecurityToken = artifacts.require("./tokens/SecurityToken.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const VolumeRestrictionTMFactory = artifacts.require('./VolumeRestrictionTMFactory.sol') const VolumeRestrictionTMLogic = artifacts.require('./VolumeRestrictionTM.sol'); const VolumeRestrictionLib = artifacts.require('./VolumeRestrictionLib.sol'); @@ -257,6 +259,14 @@ module.exports = function(deployer, network, accounts) { // manager attach with the securityToken contract at the time of deployment) return deployer.deploy(CappedSTOLogic, nullAddress, nullAddress, { from: PolymathAccount }); }) + .then(() => { + // B) Deploy the DataStoreLogic Contract + return deployer.deploy(DataStoreLogic, { from: PolymathAccount }); + }) + .then(() => { + // B) Deploy the DataStoreFactory Contract + return deployer.deploy(DataStoreFactory, DataStoreLogic.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) @@ -313,7 +323,7 @@ module.exports = function(deployer, network, accounts) { }) .then(() => { // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. - return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, { from: PolymathAccount }); + return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, DataStoreFactory.address, { from: PolymathAccount }); }) .then(() => { // K) Deploy the FeatureRegistry contract to control feature switches diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 130f0ff62..a28a7c957 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -40,6 +40,8 @@ const DummySTO = artifacts.require("./DummySTO.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const STRGetter = artifacts.require("./STRGetter.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const VolumeRestrictionTMFactory = artifacts.require("./VolumeRestrictionTMFactory.sol"); const VolumeRestrictionTM = artifacts.require("./VolumeRestrictionTM.sol"); const VestingEscrowWalletFactory = artifacts.require("./VestingEscrowWalletFactory.sol"); @@ -205,7 +207,9 @@ async function deployGTM(account_polymath) { } async function deploySTFactory(account_polymath) { - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); + let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); assert.notEqual(I_STFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", "STFactory contract was not deployed"); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index bc7a2731d..d723f4e45 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -12,6 +12,9 @@ const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); const STFactory = artifacts.require("./STFactory.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); + const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -572,8 +575,10 @@ contract("SecurityTokenRegistry", async (accounts) => { describe("Generate SecurityToken v2", async () => { it("Should deploy the st version 2", async () => { // Step 7: Deploy the STFactory contract + let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); + let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); - I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); assert.notEqual( I_STFactory002.address.valueOf(), diff --git a/test/o_security_token.js b/test/o_security_token.js index aac62b9e0..d6adbbc99 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -591,7 +591,7 @@ contract("SecurityToken", async (accounts) => { await catchRevert(I_SecurityToken.transfer(accounts[7], new BN(10).pow(new BN(17)), { from: account_investor1 })); }); - it("Should adjust granularity", async () => { + it("Should not allow 0 granularity", async () => { await catchRevert(I_SecurityToken.changeGranularity(0, { from: token_owner })); }); @@ -601,6 +601,21 @@ contract("SecurityToken", async (accounts) => { await I_SecurityToken.transfer(account_investor1, new BN(10).pow(new BN(17)), { from: accounts[7], gas: 2500000 }); }); + it("Should not allow unauthorized address to change data store", async () => { + await catchRevert(I_SecurityToken.changeDataStore(one_address, { from: account_polymath })); + }); + + it("Should not allow 0x0 address as data store", async () => { + await catchRevert(I_SecurityToken.changeDataStore(address_zero, { from: token_owner })); + }); + + it("Should change data store", async () => { + let ds = await I_SecurityToken.dataStore(); + await I_SecurityToken.changeDataStore(one_address, { from: token_owner }); + assert.equal(one_address, await I_SecurityToken.dataStore()); + await I_SecurityToken.changeDataStore(ds, { from: token_owner }); + }); + 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], new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1, gas: 2500000 }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 3c52dc693..624217939 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -13,6 +13,8 @@ const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager. const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); +const DataStoreLogic = artifacts.require('./DataStore.sol'); +const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -151,7 +153,9 @@ contract("ModuleRegistryProxy", async (accounts) => { 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 }); + let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); + let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); assert.notEqual(I_STFactory.address.valueOf(), address_zero, "STFactory contract was not deployed"); }); diff --git a/test/za_datastore.js b/test/za_datastore.js new file mode 100644 index 000000000..b89646bac --- /dev/null +++ b/test/za_datastore.js @@ -0,0 +1,468 @@ +import latestTime from "./helpers/latestTime"; +import { catchRevert } from "./helpers/exceptions"; +import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; +import { setUpPolymathNetwork } from "./helpers/createInstances"; +const SecurityToken = artifacts.require("./SecurityToken.sol"); +const DataStore = artifacts.require("./DataStore.sol"); + +const Web3 = require("web3"); +let BN = Web3.utils.BN; +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +contract("Data store", async (accounts) => { + // Accounts Variable declaration + let account_polymath; + let token_owner; + + // Contract Instance Declaration + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_STRProxied; + let I_STFactory; + let I_SecurityToken; + let I_PolyToken; + let I_PolymathRegistry; + let I_DataStore; + let I_ModuleRegistryProxy; + let I_MRProxied; + let I_STRGetter; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const contact = "team@polymath.network"; + const key = "0x41"; + const key2 = "0x42"; + const bytes32data = "0x4200000000000000000000000000000000000000000000000000000000000000"; + const bytes32data2 = "0x4400000000000000000000000000000000000000000000000000000000000000"; + + // Initial fee for ticker registry and security token registry + const initRegFee = new BN(web3.utils.toWei("250")); + + const address_zero = "0x0000000000000000000000000000000000000000"; + const address_one = "0x0000000000000000000000000000000000000001"; + const address_two = "0x0000000000000000000000000000000000000002"; + + before(async () => { + account_polymath = accounts[0]; + token_owner = accounts[1]; + + // 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, + I_STRGetter + ] = instances; + + + + // 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} + 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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + + const log = (await I_SecurityToken.getPastEvents('ModuleAdded', { filter: { transactionHash: tx.transactionHash } }))[0]; + + // 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 fetch data store address", async () => { + I_DataStore = await DataStore.at(await I_SecurityToken.dataStore()); + }); + }); + + describe("Should attach to security token securely", async () => { + it("Should be attached to a security token upon deployment", async () => { + assert.equal(await I_DataStore.securityToken(), I_SecurityToken.address, "Incorrect Security Token attached"); + }); + + it("Should not allow non-issuer to change security token address", async () => { + await catchRevert(I_DataStore.setSecurityToken(address_one, { from: account_polymath })); + }); + + it("Should allow issuer to change security token address", async () => { + let snapId = await takeSnapshot(); + await I_DataStore.setSecurityToken(address_one, { from: token_owner }); + assert.equal(await I_DataStore.securityToken(), address_one, "Incorrect Security Token attached"); + await revertToSnapshot(snapId); + assert.equal(await I_DataStore.securityToken(), I_SecurityToken.address, "Incorrect Security Token attached"); + }); + }); + + describe("Should set data correctly", async () => { + it("Should set and fetch uint256 correctly", async () => { + await catchRevert(I_DataStore.setUint256("0x0", 1, { from: token_owner })); + await I_DataStore.setUint256(key, 1, { from: token_owner }); + assert.equal((await I_DataStore.getUint256(key)).toNumber(), 1, "Incorrect Data Inserted"); + }); + + it("Should set and fetch bytes32 correctly", async () => { + await I_DataStore.setBytes32(key, bytes32data, { from: token_owner }); + assert.equal(await I_DataStore.getBytes32(key), bytes32data, "Incorrect Data Inserted"); + }); + + it("Should set and fetch address correctly", async () => { + await I_DataStore.setAddress(key, address_one, { from: token_owner }); + assert.equal(await I_DataStore.getAddress(key), address_one, "Incorrect Data Inserted"); + }); + + it("Should set and fetch string correctly", async () => { + await I_DataStore.setString(key, name, { from: token_owner }); + assert.equal(await I_DataStore.getString(key), name, "Incorrect Data Inserted"); + }); + + it("Should set and fetch bytes correctly", async () => { + await I_DataStore.setBytes(key, bytes32data, { from: token_owner }); + assert.equal(await I_DataStore.getBytes(key), bytes32data, "Incorrect Data Inserted"); + }); + + it("Should set and fetch bool correctly", async () => { + await I_DataStore.setBool(key, true, { from: token_owner }); + assert.equal(await I_DataStore.getBool(key), true, "Incorrect Data Inserted"); + }); + + it("Should set and fetch uint256 array correctly", async () => { + let arr = [1, 2]; + await I_DataStore.setUint256Array(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getUint256Array(key); + let arrLen = await I_DataStore.getUint256ArrayLength(key); + let arrElement2 = await I_DataStore.getUint256ArrayElement(key, 1); + assert.equal(arr2[0].toNumber(), arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1].toNumber(), arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2.toNumber(), arr[1], "Incorrect array element"); + }); + + it("Should set and fetch bytes32 array correctly", async () => { + let arr = [bytes32data, bytes32data2]; + await I_DataStore.setBytes32Array(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getBytes32Array(key); + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + let arrElement2 = await I_DataStore.getBytes32ArrayElement(key, 1); + assert.equal(arr2[0], arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1], arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2, arr[1], "Incorrect array element"); + }); + + it("Should set and fetch address array correctly", async () => { + let arr = [address_zero, address_one]; + await I_DataStore.setAddressArray(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getAddressArray(key); + let arrLen = await I_DataStore.getAddressArrayLength(key); + let arrElement2 = await I_DataStore.getAddressArrayElement(key, 1); + assert.equal(arr2[0], arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1], arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2, arr[1], "Incorrect array element"); + }); + + it("Should set and fetch bool array correctly", async () => { + let arr = [false, true]; + await I_DataStore.setBoolArray(key, arr, { from: token_owner }); + let arr2 = await I_DataStore.getBoolArray(key); + let arrLen = await I_DataStore.getBoolArrayLength(key); + let arrElement2 = await I_DataStore.getBoolArrayElement(key, 1); + assert.equal(arr2[0], arr[0], "Incorrect Data Inserted"); + assert.equal(arr2[1], arr[1], "Incorrect Data Inserted"); + assert.equal(arrLen, arr.length, "Incorrect Array Length"); + assert.equal(arrElement2, arr[1], "Incorrect array element"); + }); + + it("Should insert uint256 into Array", async () => { + let arrLen = await I_DataStore.getUint256ArrayLength(key); + await I_DataStore.insertUint256(key, new BN(10), { from: token_owner }); + let arrElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement.toNumber(), 10, "Incorrect array element"); + }); + + it("Should insert bytes32 into Array", async () => { + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + await I_DataStore.insertBytes32(key, bytes32data, { from: token_owner }); + let arrElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, bytes32data, "Incorrect array element"); + }); + + it("Should insert address into Array", async () => { + let arrLen = await I_DataStore.getAddressArrayLength(key); + await I_DataStore.insertAddress(key, address_one, { from: token_owner }); + let arrElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, address_one, "Incorrect array element"); + }); + + it("Should insert bool into Array", async () => { + let arrLen = await I_DataStore.getBoolArrayLength(key); + await I_DataStore.insertBool(key, true, { from: token_owner }); + let arrElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, true, "Incorrect array element"); + }); + + it("Should delete uint256 from Array", async () => { + let arrLen = await I_DataStore.getUint256ArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteUint256(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement.toNumber(), (await I_DataStore.getUint256ArrayElement(key, indexToDelete)).toNumber(), "Incorrect array element"); + }); + + it("Should delete bytes32 from Array", async () => { + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteBytes32(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement, await I_DataStore.getBytes32ArrayElement(key, indexToDelete), "Incorrect array element"); + }); + + it("Should delete address from Array", async () => { + let arrLen = await I_DataStore.getAddressArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteAddress(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement, await I_DataStore.getAddressArrayElement(key, indexToDelete), "Incorrect array element"); + }); + + it("Should delete bool from Array", async () => { + let arrLen = await I_DataStore.getBoolArrayLength(key); + let indexToDelete = arrLen.toNumber() - 2; + let lastElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber() - 1); + await I_DataStore.deleteBool(key, indexToDelete, { from: token_owner }); + assert.equal(arrLen.toNumber() - 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(lastElement, await I_DataStore.getBoolArrayElement(key, indexToDelete), "Incorrect array element"); + }); + + it("Should set and fetch multiple uint256 correctly", async () => { + await catchRevert(I_DataStore.setUint256Multi([key], [1,2], { from: token_owner })); + await I_DataStore.setUint256Multi([key, key2], [1,2], { from: token_owner }); + assert.equal((await I_DataStore.getUint256(key)).toNumber(), 1, "Incorrect Data Inserted"); + assert.equal((await I_DataStore.getUint256(key2)).toNumber(), 2, "Incorrect Data Inserted"); + }); + + it("Should set and fetch multiple bytes32 correctly", async () => { + await I_DataStore.setBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: token_owner }); + assert.equal(await I_DataStore.getBytes32(key), bytes32data, "Incorrect Data Inserted"); + assert.equal(await I_DataStore.getBytes32(key2), bytes32data2, "Incorrect Data Inserted"); + }); + + it("Should set and fetch multiple address correctly", async () => { + await I_DataStore.setAddressMulti([key, key2], [address_one, address_two], { from: token_owner }); + assert.equal(await I_DataStore.getAddress(key), address_one, "Incorrect Data Inserted"); + assert.equal(await I_DataStore.getAddress(key2), address_two, "Incorrect Data Inserted"); + }); + + it("Should set and fetch multiple bool correctly", async () => { + await I_DataStore.setBoolMulti([key, key2], [true, true], { from: token_owner }); + assert.equal(await I_DataStore.getBool(key), true, "Incorrect Data Inserted"); + assert.equal(await I_DataStore.getBool(key2), true, "Incorrect Data Inserted"); + }); + + it("Should insert multiple uint256 into multiple Array", async () => { + let arrLen = await I_DataStore.getUint256ArrayLength(key); + let arrLen2 = await I_DataStore.getUint256ArrayLength(key2); + await I_DataStore.insertUint256Multi([key, key2], [10, 20], { from: token_owner }); + let arrElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getUint256ArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement.toNumber(), 10, "Incorrect array element"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement2.toNumber(), 20, "Incorrect array element"); + }); + + it("Should insert multiple bytes32 into multiple Array", async () => { + let arrLen = await I_DataStore.getBytes32ArrayLength(key); + let arrLen2 = await I_DataStore.getBytes32ArrayLength(key2); + await I_DataStore.insertBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: token_owner }); + let arrElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getBytes32ArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, bytes32data, "Incorrect array element"); + assert.equal(arrElement2, bytes32data2, "Incorrect array element"); + }); + + it("Should insert multiple address into multiple Array", async () => { + let arrLen = await I_DataStore.getAddressArrayLength(key); + let arrLen2 = await I_DataStore.getAddressArrayLength(key2); + await I_DataStore.insertAddressMulti([key, key2], [address_one, address_two], { from: token_owner }); + let arrElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getAddressArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, address_one, "Incorrect array element"); + assert.equal(arrElement2, address_two, "Incorrect array element"); + }); + + it("Should insert multiple bool into multiple Array", async () => { + let arrLen = await I_DataStore.getBoolArrayLength(key); + let arrLen2 = await I_DataStore.getBoolArrayLength(key2); + await I_DataStore.insertBoolMulti([key, key2], [true, true], { from: token_owner }); + let arrElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber()); + let arrElement2 = await I_DataStore.getBoolArrayElement(key2, arrLen2.toNumber()); + assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); + assert.equal(arrLen2.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key2)).toNumber(), "Incorrect Array Length"); + assert.equal(arrElement, true, "Incorrect array element"); + assert.equal(arrElement2, true, "Incorrect array element"); + }); + }); + + describe("Should not allow unautohrized modification to data", async () => { + it("Should not allow unauthorized addresses to modify uint256", async () => { + await catchRevert(I_DataStore.setUint256(key, new BN(1), { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify bytes32", async () => { + await catchRevert(I_DataStore.setBytes32(key, bytes32data, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify address", async () => { + await catchRevert(I_DataStore.setAddress(key, address_one, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify string", async () => { + await catchRevert(I_DataStore.setString(key, name, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify bytes", async () => { + await catchRevert(I_DataStore.setBytes32(key, bytes32data, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify bool", async () => { + await catchRevert(I_DataStore.setBool(key, true, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify uint256 array", async () => { + let arr = [1, 2]; + await catchRevert(I_DataStore.setUint256Array(key, arr, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify bytes32 array", async () => { + let arr = [bytes32data, bytes32data2]; + await catchRevert(I_DataStore.setBytes32Array(key, arr, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify address array", async () => { + let arr = [address_zero, address_one]; + await catchRevert(I_DataStore.setAddressArray(key, arr, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify bool array", async () => { + let arr = [false, true]; + await catchRevert(I_DataStore.setBoolArray(key, arr, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert uint256 into Array", async () => { + await catchRevert(I_DataStore.insertUint256(key, new BN(10), { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert bytes32 into Array", async () => { + await catchRevert(I_DataStore.insertBytes32(key, bytes32data, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert address into Array", async () => { + await catchRevert(I_DataStore.insertAddress(key, address_one, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert bool into Array", async () => { + await catchRevert(I_DataStore.insertBool(key, true, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to delete uint256 from Array", async () => { + await catchRevert(I_DataStore.deleteUint256(key, 0, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to delete bytes32 from Array", async () => { + await catchRevert(I_DataStore.deleteBytes32(key, 0, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to delete address from Array", async () => { + await catchRevert(I_DataStore.deleteAddress(key, 0, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to delete bool from Array", async () => { + await catchRevert(I_DataStore.deleteBool(key, 0, { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple uint256", async () => { + await catchRevert(I_DataStore.setUint256Multi([key, key2], [1,2], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple bytes32", async () => { + await catchRevert(I_DataStore.setBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple address", async () => { + await catchRevert(I_DataStore.setAddressMulti([key, key2], [address_one, address_two], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to modify multiple bool", async () => { + await catchRevert(I_DataStore.setBoolMulti([key, key2], [true, true], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple uint256 into multiple Array", async () => { + await catchRevert(I_DataStore.insertUint256Multi([key, key2], [10, 20], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple bytes32 into multiple Array", async () => { + await catchRevert(I_DataStore.insertBytes32Multi([key, key2], [bytes32data, bytes32data2], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple address into multiple Array", async () => { + await catchRevert(I_DataStore.insertAddressMulti([key, key2], [address_one, address_two], { from: account_polymath })); + }); + + it("Should not allow unauthorized addresses to insert multiple bool into multiple Array", async () => { + await catchRevert(I_DataStore.insertBoolMulti([key, key2], [true, true], { from: account_polymath })); + }); + }); +}); \ No newline at end of file From 5934f5429b37a37ccda686506fe8e5659316eaa4 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Thu, 31 Jan 2019 09:08:50 -0400 Subject: [PATCH 088/119] Signing: Use library and improve tests --- .../TransferManager/SignedTransferManager.sol | 43 +----- .../SignedTransferManagerFactory.sol | 4 +- .../GeneralTransferManager.sol | 16 +- test/h_general_transfer_manager.js | 138 ++++++++++-------- test/helpers/signData.js | 13 +- test/zb_signed_transfer_manager.js | 17 +-- 6 files changed, 111 insertions(+), 120 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index ea7edffe9..94931675d 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -4,12 +4,14 @@ import "../../TransferManager/TransferManager.sol"; import "../../../interfaces/IDataStore.sol"; import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; /** * @title Transfer Manager module for verifing transations with a signed message */ contract SignedTransferManager is TransferManager { using SafeMath for uint256; + using ECDSA for bytes32; bytes32 constant public ADMIN = "ADMIN"; @@ -25,7 +27,7 @@ contract SignedTransferManager is TransferManager { event SignersUpdated(address[] _signers, bool[] _signersStats); // Emit when a signature has been deemed invalid - event SignatureInvalidated(bytes _data); + event SignatureUsed(bytes _data); /** @@ -108,8 +110,7 @@ contract SignedTransferManager is TransferManager { return Result.NA; bytes32 hash = keccak256(abi.encodePacked(targetAddress, nonce, expiry, _from, _to, _amount)); - bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - address signer = _recoverSignerAdd(prependedHash, signature); + address signer = hash.toEthSignedMessageHash().recover(signature); if (!_checkSigner(signer)) { return Result.NA; @@ -134,7 +135,7 @@ contract SignedTransferManager is TransferManager { */ function invalidateSignature(address _from, address _to, uint256 _amount, bytes calldata _data) external { require(_checkSigner(msg.sender), "Unauthorized Signer"); - + address targetAddress; uint256 nonce; uint256 expiry; @@ -145,41 +146,11 @@ contract SignedTransferManager is TransferManager { require(targetAddress == address(this), "Signature not for this module"); bytes32 hash = keccak256(abi.encodePacked(targetAddress, nonce, expiry, _from, _to, _amount)); - bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - - require(_recoverSignerAdd(prependedHash, signature) == msg.sender, "Incorrect Signer"); + require(hash.toEthSignedMessageHash().recover(signature) == msg.sender, "Incorrect Signer"); _invalidateSignature(signature); } - /** - * @notice used to recover signers' address from signature - */ - function _recoverSignerAdd(bytes32 _hash, bytes memory _data) internal pure returns(address) { - - if (_data.length != 65) { - return address(0); - } - - bytes32 r; - bytes32 s; - uint8 v; - - assembly { - r := mload(add(_data, 32)) - s := mload(add(_data, 64)) - v := and(mload(add(_data, 65)), 255) - } - if (v < 27) { - v += 27; - } - if (v != 27 && v != 28) { - - } - - return ecrecover(_hash, v, r, s); - } - /** * @notice Return the permissions flag that are associated with ManualApproval transfer manager */ @@ -202,6 +173,6 @@ contract SignedTransferManager is TransferManager { function _invalidateSignature(bytes memory _data) internal { IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); dataStore.setBool(keccak256(abi.encodePacked(INVALID_SIG, _data)), true); - emit SignatureInvalidated(_data); + emit SignatureUsed(_data); } } diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol index d38d82758..bf23eedf8 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol @@ -38,7 +38,7 @@ contract SignedTransferManagerFactory is ModuleFactory { function deploy(bytes calldata /* _data */) external returns(address) { address polyToken = _takeFee(); SignedTransferManager signedTransferManager = new SignedTransferManager(msg.sender, polyToken); - emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, now); + emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(signedTransferManager); } @@ -100,7 +100,7 @@ contract SignedTransferManagerFactory is ModuleFactory { */ function getTags() public view returns(bytes32[] memory) { bytes32[] memory availableTags = new bytes32[](2); - availableTags[0] = "General"; + availableTags[0] = "Signed"; availableTags[1] = "Transfer Restriction"; return availableTags; } diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index b4889dd36..746b994c2 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -4,12 +4,14 @@ import "./TransferManager.sol"; import "../../storage/GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; /** * @title Transfer Manager module for core transfer validation functionality */ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManager { using SafeMath for uint256; + using ECDSA for bytes32; // Emit when Issuance address get changed event ChangeIssuanceAddress(address _issuanceAddress); @@ -257,9 +259,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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 + * @param _signature issuer signature */ function modifyWhitelistSigned( address _investor, @@ -270,9 +270,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256 _validFrom, uint256 _validTo, uint256 _nonce, - uint8 _v, - bytes32 _r, - bytes32 _s + bytes memory _signature ) public { @@ -285,17 +283,17 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage bytes32 hash = keccak256( abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); - _checkSig(hash, _v, _r, _s); + _checkSig(hash, _signature); _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** * @notice Used to verify the signature */ - function _checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view { + function _checkSig(bytes32 _hash, bytes memory _signature) internal view { //Check that the signature is valid //sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address - address signer = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), _v, _r, _s); + address signer = _hash.toEthSignedMessageHash().recover(_signature); require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer"); } diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 83f297ae7..03c22b23f 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -1,7 +1,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; -import { signData } from "./helpers/signData"; +import { getSignGTMData, signData } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; @@ -84,6 +84,7 @@ contract("GeneralTransferManager", async (accounts) => { let currentTime; const address_zero = "0x0000000000000000000000000000000000000000"; const one_address = "0x0000000000000000000000000000000000000001"; + let signer; before(async () => { currentTime = new BN(await latestTime()); @@ -108,6 +109,12 @@ contract("GeneralTransferManager", async (accounts) => { account_affiliates1 = accounts[3]; account_affiliates2 = accounts[4]; + let oneeth = new BN(web3.utils.toWei("1", "ether")); + signer = web3.eth.accounts.create(); + await web3.eth.personal.importRawKey(signer.privateKey, ""); + await web3.eth.personal.unlockAccount(signer.address, "", 6000); + await web3.eth.sendTransaction({ from: token_owner, to: signer.address, value: oneeth }); + // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -444,13 +451,29 @@ contract("GeneralTransferManager", async (accounts) => { await catchRevert(I_DummySTO.generateTokens(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); }); + it("Should provide the permission and change the signing address", async () => { + let log = await I_GeneralPermissionManager.addDelegate(account_delegate, web3.utils.fromAscii("My details"), { from: token_owner }); + assert.equal(log.logs[0].args._delegate, account_delegate); + + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { + from: token_owner + }); + + assert.isTrue( + await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS")) + ); + console.log(JSON.stringify(signer)); + let tx = await I_GeneralTransferManager.changeSigningAddress(signer.address, { from: account_delegate }); + assert.equal(tx.logs[0].args._signingAddress, signer.address); + }); + 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 = await latestTime(); let validTo = await latestTime() + duration.days(5); let nonce = 5; - const sig = signData( + const sig = getSignGTMData( account_investor2, account_investor2, fromTime, @@ -460,13 +483,9 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - token_owner_pk + signer.privateKey ); - 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, @@ -477,9 +496,7 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - v, - r, - s, + sig, { from: account_investor2, gas: 6000000 @@ -494,7 +511,7 @@ contract("GeneralTransferManager", async (accounts) => { let validFrom = await latestTime() - 100; let validTo = await latestTime() - 1; let nonce = 5; - const sig = signData( + const sig = getSignGTMData( I_GeneralTransferManager.address, account_investor2, fromTime, @@ -504,13 +521,9 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - token_owner_pk + signer.privateKey ); - 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, @@ -521,9 +534,7 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - v, - r, - s, + sig, { from: account_investor2, gas: 6000000 @@ -538,7 +549,7 @@ contract("GeneralTransferManager", async (accounts) => { let validFrom = await latestTime(); let validTo = await latestTime() + 60 * 60; let nonce = 5; - const sig = signData( + const sig = getSignGTMData( account_investor2, account_investor2, fromTime, @@ -551,10 +562,6 @@ contract("GeneralTransferManager", async (accounts) => { "2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200" ); - 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, @@ -565,9 +572,7 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - v, - r, - s, + sig, { from: account_investor2, gas: 6000000 @@ -576,13 +581,13 @@ contract("GeneralTransferManager", async (accounts) => { ); }); - it("Should Buy the tokens", async () => { + it("Should Buy the tokens with signers signature", async () => { // Add the Investor in to the whitelist //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk let validFrom = await latestTime(); let validTo = await latestTime() + duration.days(5); let nonce = 5; - const sig = signData( + const sig = getSignGTMData( I_GeneralTransferManager.address, account_investor2, currentTime.toNumber(), @@ -592,13 +597,9 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - token_owner_pk + signer.privateKey ); - 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, currentTime.toNumber(), @@ -608,9 +609,7 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - v, - r, - s, + sig, { from: account_investor2, gas: 6000000 @@ -638,7 +637,7 @@ contract("GeneralTransferManager", async (accounts) => { let validFrom = await latestTime(); let validTo = await latestTime() + duration.days(5); let nonce = 5; - const sig = signData( + const sig = getSignGTMData( I_GeneralTransferManager.address, account_investor2, currentTime.toNumber(), @@ -648,13 +647,9 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - token_owner_pk + signer.privateKey ); - 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, @@ -665,9 +660,7 @@ contract("GeneralTransferManager", async (accounts) => { validFrom, validTo, nonce, - v, - r, - s, + sig, { from: account_investor2, gas: 6000000 @@ -676,6 +669,43 @@ contract("GeneralTransferManager", async (accounts) => { ); }); + it("Should sign with token owner key", async () => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = await latestTime(); + let validTo = await latestTime() + duration.days(5); + let nonce = 6; + const sig = getSignGTMData( + I_GeneralTransferManager.address, + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + validFrom, + validTo, + nonce, + "0x" + token_owner_pk + ); + + await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + validFrom, + validTo, + nonce, + sig, + { + from: account_investor2, + gas: 6000000 + } + ) + + }); + it("Should fail in changing the signing address", async () => { await catchRevert(I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_investor4 })); }); @@ -686,22 +716,6 @@ contract("GeneralTransferManager", async (accounts) => { 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, web3.utils.fromAscii("My details"), { from: token_owner }); - assert.equal(log.logs[0].args._delegate, account_delegate); - - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { - from: token_owner - }); - - assert.isTrue( - await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("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 () => { await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_polymath })); }); diff --git a/test/helpers/signData.js b/test/helpers/signData.js index cb551102e..3acbc6d4c 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -13,19 +13,28 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest ) .slice(2); packedData = new Buffer(packedData, "hex"); + console.log("PackedData 1: " + packedData); packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); packedData = web3.utils.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); + console.log("PackedData 2: " + packedData); return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } -function getSignTMData(tmAddress, nonce, expiry, fromAddress, toAddress, amount, pk) { +function getSignSTMData(tmAddress, nonce, expiry, fromAddress, toAddress, amount, pk) { let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'uint256', v: new BN(nonce)}, {t: 'uint256', v: new BN(expiry)}, {t: 'address', v: fromAddress}, {t: 'address', v: toAddress}, {t: 'uint256', v: new BN(amount)}); let signature = (web3.eth.accounts.sign(hash, pk)).signature; let data = web3.eth.abi.encodeParameters(['address', 'uint256', 'uint256', 'bytes'], [tmAddress, new BN(nonce).toString(), new BN(expiry).toString(), signature]); return data; } +function getSignGTMData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { + let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: investorAddress}, {t: 'uint256', v: new BN(fromTime)}, {t: 'uint256', v: new BN(toTime)}, {t: 'uint256', v: new BN(expiryTime)}, {t: 'bool', v: restricted}, {t: 'uint256', v: new BN(validFrom)}, {t: 'uint256', v: new BN(validTo)}, {t: 'uint256', v: new BN(nonce)}); + let signature = (web3.eth.accounts.sign(hash, pk)); + return signature.signature; +} + module.exports = { signData, - getSignTMData + getSignSTMData, + getSignGTMData }; diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index e13b99f46..a35baba07 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -1,7 +1,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; -import { getSignTMData } from "./helpers/signData"; +import { getSignSTMData } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; @@ -117,7 +117,7 @@ contract("SignedTransferManager", accounts => { FeatureRegistry: ${I_FeatureRegistry.address} ManualApprovalTransferManagerFactory: ${I_SignedTransferManagerFactory.address} - + ----------------------------------------------------------------------------- `); @@ -133,7 +133,7 @@ contract("SignedTransferManager", 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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -223,10 +223,10 @@ contract("SignedTransferManager", accounts => { await web3.eth.sendTransaction({ from: token_owner, to: signer.address, value: oneeth }); await I_SignedTransferManager.updateSigners([signer.address], [true], {from: token_owner}); - + let nonce = new BN(10); let expiry = new BN(currentTime.add(new BN(duration.days(100)))); - let data = await getSignTMData( + let data = await getSignSTMData( I_SignedTransferManager.address, nonce, expiry, @@ -247,7 +247,7 @@ contract("SignedTransferManager", accounts => { let oneeth = new BN(web3.utils.toWei("1", "ether")); let nonce = new BN(10); let expiry = new BN(currentTime.add(new BN(duration.days(100)))); - let data = await getSignTMData( + let data = await getSignSTMData( I_SignedTransferManager.address, nonce, expiry, @@ -270,7 +270,7 @@ contract("SignedTransferManager", accounts => { assert.equal(balance11.sub(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor1)).toString()); assert.equal(balance21.add(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor2)).toString()); - + }); it("should not allow transfer if the signer is not on the signer list", async () => { @@ -278,7 +278,7 @@ contract("SignedTransferManager", accounts => { let oneeth = new BN(web3.utils.toWei("1", "ether")); let nonce = new BN(10); let expiry = new BN(currentTime.add(new BN(duration.days(100)))); - let data = await getSignTMData( + let data = await getSignSTMData( I_SignedTransferManager.address, nonce, expiry, @@ -292,4 +292,3 @@ contract("SignedTransferManager", accounts => { }); }); }); - From 7c95eee5b6380499570f32e48ecfb376efafe2d4 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 31 Jan 2019 18:56:40 +0530 Subject: [PATCH 089/119] minor improvement --- .../Experimental/TransferManager/SignedTransferManager.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index 94931675d..7b0fb4ec2 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -116,10 +116,8 @@ contract SignedTransferManager is TransferManager { return Result.NA; } else if(_isTransfer) { _invalidateSignature(signature); - return Result.VALID; - } else { - return Result.VALID; } + return Result.VALID; } return Result.NA; } From bd26204c5346577b705cafff5cee8f9aeb1cb32e Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 1 Feb 2019 17:35:33 +0530 Subject: [PATCH 090/119] migrate data of gtm --- contracts/interfaces/IBoot.sol | 2 + .../modules/Checkpoint/DividendCheckpoint.sol | 1 - .../Experimental/Burn/TrackedRedemption.sol | 1 - .../Mixed/ScheduledCheckpoint.sol | 1 - .../TransferManager/KYCTransferManager.sol | 1 - .../TransferManager/SignedTransferManager.sol | 2 - .../Wallet/VestingEscrowWallet.sol | 1 - contracts/modules/Module.sol | 8 +- .../GeneralPermissionManager.sol | 1 - contracts/modules/STO/CappedSTO.sol | 1 - contracts/modules/STO/DummySTO.sol | 1 - contracts/modules/STO/PreSaleSTO.sol | 1 - contracts/modules/STO/USDTieredSTO.sol | 1 - .../TransferManager/CountTransferManager.sol | 1 - .../GeneralTransferManager.sol | 125 ++++++++++++------ .../GeneralTransferManagerFactory.sol | 2 + .../storage/GeneralTransferManagerStorage.sol | 95 +++++++------ 17 files changed, 147 insertions(+), 98 deletions(-) diff --git a/contracts/interfaces/IBoot.sol b/contracts/interfaces/IBoot.sol index 9e295fb2f..437a24523 100644 --- a/contracts/interfaces/IBoot.sol +++ b/contracts/interfaces/IBoot.sol @@ -6,4 +6,6 @@ interface IBoot { * @return bytes4 Configure function signature */ function getInitFunction() external pure returns(bytes4); + + function initialize() external; } \ No newline at end of file diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 92a89dc01..3bfc358d8 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -10,7 +10,6 @@ pragma solidity ^0.5.0; import "./ICheckpoint.sol"; import "./DividendCheckpointStorage.sol"; import "../Module.sol"; -import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/math/Math.sol"; diff --git a/contracts/modules/Experimental/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol index 9b86ef82f..eda7ca14c 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -2,7 +2,6 @@ pragma solidity ^0.5.0; import "../../Burn/IBurn.sol"; import "../../Module.sol"; -import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index e2aed863f..9cc14c730 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -2,7 +2,6 @@ pragma solidity ^0.5.0; import "./../../Checkpoint/ICheckpoint.sol"; import "../../TransferManager/TransferManager.sol"; -import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol index 7a314220e..a4bd779e0 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; import "../../TransferManager/TransferManager.sol"; -import "../../../interfaces/IDataStore.sol"; import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index 7b0fb4ec2..69fed8036 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -1,8 +1,6 @@ pragma solidity ^0.5.0; import "../../TransferManager/TransferManager.sol"; -import "../../../interfaces/IDataStore.sol"; -import "../../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; diff --git a/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol index 5b483cdf5..e0231aacd 100644 --- a/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol @@ -3,7 +3,6 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../../../storage/VestingEscrowWalletStorage.sol"; import "./IWallet.sol"; -import "../../../interfaces/ISecurityToken.sol"; /** * @title Wallet for core vesting escrow functionality diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index f6c967f77..1aef9e4e8 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -1,9 +1,11 @@ pragma solidity ^0.5.0; +import "./ModuleStorage.sol"; import "../interfaces/IModule.sol"; +import "../interfaces/IDatastore.sol"; +import "../interfaces/ISecurityToken.sol"; import "../interfaces/ICheckPermission.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "./ModuleStorage.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; /** @@ -58,4 +60,8 @@ contract Module is IModule, ModuleStorage { require(polyToken.transferFrom(securityToken, Ownable(factory).owner(), _amount), "Unable to take fee"); return true; } + + function getDataStore() public view returns(address) { + return ISecurityToken(securityToken).dataStore(); + } } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 6469ac3bb..6ce855897 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -3,7 +3,6 @@ pragma solidity ^0.5.0; import "./IPermissionManager.sol"; import "../Module.sol"; import "./GeneralPermissionManagerStorage.sol"; -import "../../interfaces/ISecurityToken.sol"; /** * @title Permission Manager module for core permissioning functionality diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 596936e37..8286da28f 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; import "./STO.sol"; -import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./CappedSTOStorage.sol"; diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 5a4e5e560..e264685a7 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; import "./STO.sol"; -import "../../interfaces/ISecurityToken.sol"; import "./DummySTOStorage.sol"; /** diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 09f4a1ce9..824b808fc 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; import "./STO.sol"; -import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./PreSaleSTOStorage.sol"; diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 20cce3e87..bd64aaca6 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; import "./STO.sol"; -import "../../interfaces/ISecurityToken.sol"; import "../../interfaces/IOracle.sol"; import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 9901ba714..b598505f0 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -2,7 +2,6 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; import "./CountTransferManagerStorage.sol"; -import "../../interfaces/ISecurityToken.sol"; /** * @title Transfer Manager for limiting maximum number of token holders diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 746b994c2..021f2117e 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -3,7 +3,6 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; import "../../storage/GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../../interfaces/ISecurityToken.sol"; import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; /** @@ -47,7 +46,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @notice Constructor * @param _securityToken Address of the security token */ - constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + constructor(address _securityToken, address _polyToken) + public + Module(_securityToken, _polyToken) + { } @@ -58,14 +60,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return bytes4(0); } + /** + * @notice This function use to initialize the local variables of the contract + */ + function initialize() public onlyFactory { + IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTISSUANCES, true); + } + /** * @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; + bytes memory _data = abi.encode(_defaultFromTime, _defaultToTime); + IDataStore(getDataStore()).setBytes(DEFAULTS, _data); emit ChangeDefaults(_defaultFromTime, _defaultToTime); } @@ -74,7 +83,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _issuanceAddress new address for the issuance */ function changeIssuanceAddress(address _issuanceAddress) public withPerm(FLAGS) { - issuanceAddress = _issuanceAddress; + IDataStore(getDataStore()).setAddress(ISSUANCE_ADD, _issuanceAddress); emit ChangeIssuanceAddress(_issuanceAddress); } @@ -83,7 +92,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _signingAddress new address for the signing */ function changeSigningAddress(address _signingAddress) public withPerm(FLAGS) { - signingAddress = _signingAddress; + IDataStore(getDataStore()).setAddress(SIGNING_ADD, _signingAddress); emit ChangeSigningAddress(_signingAddress); } @@ -94,7 +103,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllTransfers flag value */ function changeAllowAllTransfers(bool _allowAllTransfers) public withPerm(FLAGS) { - allowAllTransfers = _allowAllTransfers; + IDataStore(getDataStore()).setBool(ALLOWALLTRANSFERS, _allowAllTransfers); emit AllowAllTransfers(_allowAllTransfers); } @@ -105,7 +114,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllWhitelistTransfers flag value */ function changeAllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers) public withPerm(FLAGS) { - allowAllWhitelistTransfers = _allowAllWhitelistTransfers; + IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTTRANSFERS, _allowAllWhitelistTransfers); emit AllowAllWhitelistTransfers(_allowAllWhitelistTransfers); } @@ -116,7 +125,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllWhitelistIssuances flag value */ function changeAllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances) public withPerm(FLAGS) { - allowAllWhitelistIssuances = _allowAllWhitelistIssuances; + IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTISSUANCES, _allowAllWhitelistIssuances); emit AllowAllWhitelistIssuances(_allowAllWhitelistIssuances); } @@ -127,7 +136,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllBurnTransfers flag value */ function changeAllowAllBurnTransfers(bool _allowAllBurnTransfers) public withPerm(FLAGS) { - allowAllBurnTransfers = _allowAllBurnTransfers; + IDataStore(getDataStore()).setBool(ALLOWALLBURNTRANSFERS, _allowAllBurnTransfers); emit AllowAllBurnTransfers(_allowAllBurnTransfers); } @@ -149,36 +158,45 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage bool /* _isTransfer */ ) external returns(Result) { if (!paused) { - if (allowAllTransfers) { + uint64 fromTime; + uint64 fromExpiry; + uint64 toExpiry; + uint64 toTime; + uint8 canBuyFromSTO; + IDataStore dataStore = IDataStore(getDataStore()); + if (dataStore.getBool(ALLOWALLTRANSFERS)) { //All transfers allowed, regardless of whitelist return Result.VALID; } - if (allowAllBurnTransfers && (_to == address(0))) { + if (dataStore.getBool(ALLOWALLBURNTRANSFERS) && (_to == address(0))) { return Result.VALID; } - if (allowAllWhitelistTransfers) { + + (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValues(_from, _to); + + if (dataStore.getBool(ALLOWALLWHITELISTTRANSFERS)) { //Anyone on the whitelist can transfer, regardless of time - return (_onWhitelist(_to) && _onWhitelist(_from)) ? Result.VALID : Result.NA; + return (_onWhitelist(toExpiry) && _onWhitelist(fromExpiry)) ? Result.VALID : Result.NA; } - - (uint64 adjustedFromTime, uint64 adjustedToTime) = _adjustTimes(whitelist[_from].fromTime, whitelist[_to].toTime); - if (_from == issuanceAddress) { + // Using the local variables to avoid the stack too deep error + (fromTime, toTime) = _adjustTimes(fromTime, toTime); + if (_from == dataStore.getAddress(ISSUANCE_ADD)) { // Possible STO transaction, but investor not allowed to purchased from STO - if ((whitelist[_to].canBuyFromSTO == 0) && _isSTOAttached()) { + if ((canBuyFromSTO == 0) && _isSTOAttached()) { return Result.NA; } // if allowAllWhitelistIssuances is true, so time stamp ignored - if (allowAllWhitelistIssuances) { - return _onWhitelist(_to) ? Result.VALID : Result.NA; + if (dataStore.getBool(ALLOWALLWHITELISTISSUANCES)) { + return _onWhitelist(toExpiry) ? Result.VALID : Result.NA; } else { - return (_onWhitelist(_to) && (adjustedToTime <= uint64(now))) ? Result.VALID : Result.NA; + return (_onWhitelist(toExpiry) && (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) && (adjustedFromTime <= uint64(now))) && (_onWhitelist(_to) && - (adjustedToTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return ((_onWhitelist(fromExpiry) && (fromTime <= uint64(now))) && (_onWhitelist(toExpiry) && + (toTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -215,13 +233,18 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage function _modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO) internal { require(_investor != address(0), "Invalid investor"); uint8 canBuyFromSTO = 0; + uint8 added; + IDataStore dataStore = IDataStore(getDataStore()); + (,,,,added) = _kycValues(dataStore.getBytes(_getKey(WHITELIST, _investor))); if (_canBuyFromSTO) { canBuyFromSTO = 1; } - if (whitelist[_investor].added == uint8(0)) { - investors.push(_investor); + if (added == uint8(0)) { + dataStore.insertAddress(INVESTORS_ARRAY, _investor); } - whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + //whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + bytes memory _data = abi.encode(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + dataStore.setBytes(_getKey(WHITELIST, _investor), _data); emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -278,8 +301,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(_validFrom <= now, "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ require(_validTo >= now, "ValidTo is too late"); - require(!nonceMap[_investor][_nonce], "Already used signature"); - nonceMap[_investor][_nonce] = true; + bytes32 _key = keccak256(abi.encodePacked("nonceMap", _investor, _nonce)); + require(!IDataStore(getDataStore()).getBool(_key), "Already used signature"); + //nonceMap[_investor][_nonce] = true; + IDataStore(getDataStore()).setBool(_key, true); bytes32 hash = keccak256( abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _validFrom, _validTo, _nonce) ); @@ -294,16 +319,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage //Check that the signature is valid //sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address address signer = _hash.toEthSignedMessageHash().recover(_signature); - require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer"); + require(signer == Ownable(securityToken).owner() || signer == IDataStore(getDataStore()).getAddress(SIGNING_ADD), "Incorrect signer"); } /** * @notice Internal function used to check whether the investor is in the whitelist or not & also checks whether the KYC of investor get expired or not - * @param _investor Address of the investor + * @param _expiryTime Expiry time of the investor */ - function _onWhitelist(address _investor) internal view returns(bool) { - return (whitelist[_investor].expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ + function _onWhitelist(uint64 _expiryTime) internal view returns(bool) { + return (_expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ } /** @@ -320,20 +345,35 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) { uint64 adjustedFromTime = _fromTime; uint64 adjustedToTime = _toTime; + (uint64 defaultFromTime, uint64 defaultToTime) = abi.decode(IDataStore(getDataStore()).getBytes(DEFAULTS), (uint64, uint64)); if (_fromTime == 0) { - adjustedFromTime = defaults.fromTime; + adjustedFromTime = defaultFromTime; } if (_toTime == 0) { - adjustedToTime = defaults.toTime; + adjustedToTime = defaultToTime; } return (adjustedFromTime, adjustedToTime); } + function _kycValues(bytes memory _data) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added) { + return abi.decode(_data, (uint64, uint64, uint64, uint8, uint8)); + } + + function _getValues(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry ) { + IDataStore dataStore = IDataStore(getDataStore()); + (fromTime,, fromExpiry, canBuyFromSTO,) = _kycValues(dataStore.getBytes(_getKey(WHITELIST, _from))); + (, toTime, toExpiry,,) = _kycValues(dataStore.getBytes(_getKey(WHITELIST, _to))); + } + + function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1, _key2))); + } + /** * @dev Returns list of all investors */ - function getInvestors() external view returns(address[] memory) { - return investors; + function getInvestors() public view returns(address[] memory) { + return IDataStore(getDataStore()).getAddressArray(INVESTORS_ARRAY); } /** @@ -346,8 +386,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256[] memory expiryTimes, bool[] memory canBuyFromSTOs ) { - (fromTimes, toTimes, expiryTimes, canBuyFromSTOs) = _investorsData(investors); - return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + (fromTimes, toTimes, expiryTimes, canBuyFromSTOs) = _investorsData(getInvestors()); + return (getInvestors(), fromTimes, toTimes, expiryTimes, canBuyFromSTOs); } @@ -374,10 +414,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage 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) { + uint8 canBuyFromSTO; + (fromTimes[i], toTimes[i], expiryTimes[i], canBuyFromSTO,) = _kycValues( + IDataStore(getDataStore()).getBytes(_getKey(WHITELIST, _investors[i])) + ); + if (canBuyFromSTO == 0) { canBuyFromSTOs[i] = false; } else { canBuyFromSTOs[i] = true; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4c6d4a130..50bf3a6bf 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -2,6 +2,7 @@ pragma solidity ^0.5.0; import "../../proxy/GeneralTransferManagerProxy.sol"; import "../ModuleFactory.sol"; +import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying GeneralTransferManager module @@ -49,6 +50,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { GeneralTransferManagerProxy generalTransferManager = new GeneralTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); + IBoot(address(generalTransferManager)).initialize(); return address(generalTransferManager); } diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index 83418fc2a..7184a57d2 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -4,49 +4,60 @@ pragma solidity ^0.5.0; * @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 INVESTORS_ARRAY = "INVESTORS_ARRAY"; + bytes32 public constant SIGNING_ADD = "SIGNING_ADDRESS"; + bytes32 public constant ISSUANCE_ADD = "ISSUANCE_ADDRESS"; 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; - + bytes32 public constant ALLOWALLTRANSFERS = "ALLOW_ALL_TRANFERS"; + bytes32 public constant ALLOWALLWHITELISTTRANSFERS = "ALLOW_ALL_WHITELIST_TRANSFERS"; + bytes32 public constant ALLOWALLWHITELISTISSUANCES = "ALLOW_ALL_WHITELIST_ISSUANCES"; + bytes32 public constant ALLOWALLBURNTRANSFERS = "ALLOWALLBURNTRANSFERS"; + bytes32 public constant DEFAULTS = "DEFAULTS"; + + // Data Structure of GTM + /** + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + + //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; + */ } From f27311eeec92697348f02221c188ec13efa1d283 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 4 Feb 2019 14:14:47 +0530 Subject: [PATCH 091/119] high gas usage version --- contracts/modules/Module.sol | 5 + contracts/modules/STO/DummySTOFactory.sol | 12 +- .../GeneralTransferManager.sol | 8 +- .../GeneralTransferManagerFactory.sol | 4 +- .../storage/GeneralTransferManagerStorage.sol | 2 +- contracts/tokens/STFactory.sol | 2 +- contracts/tokens/SecurityToken.sol | 10 + test/h_general_transfer_manager.js | 1454 +++++++++-------- 8 files changed, 771 insertions(+), 726 deletions(-) diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 1aef9e4e8..95a73f182 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -53,6 +53,11 @@ contract Module is IModule, ModuleStorage { _; } + modifier onlyST() { + require(msg.sender == securityToken, "Unathorized"); + _; + } + /** * @notice used to withdraw the fee by the factory owner */ diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index ee84a4251..7e5ab11d2 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -46,12 +46,12 @@ contract DummySTOFactory is ModuleFactory { address polyToken = _takeFee(); //Check valid bytes - can only call module init function address dummySTO = address(new DummySTOProxy(msg.sender, polyToken, logicContract)); - //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == IBoot(dummySTO).getInitFunction(), "Invalid data"); - bool success; - /*solium-disable-next-line security/no-low-level-calls*/ - (success, ) = dummySTO.call(_data); - require(success, "Unsuccessfull call"); + // //Checks that _data is valid (not calling anything it shouldn't) + // require(Util.getSig(_data) == IBoot(dummySTO).getInitFunction(), "Invalid data"); + // bool success; + // /*solium-disable-next-line security/no-low-level-calls*/ + // (success, ) = dummySTO.call(_data); + // require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(dummySTO, getName(), address(this), msg.sender, setupCost, now); return dummySTO; diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 021f2117e..432e1282a 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -63,7 +63,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage /** * @notice This function use to initialize the local variables of the contract */ - function initialize() public onlyFactory { + function initialize() public onlyST { IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTISSUANCES, true); } @@ -235,13 +235,17 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint8 canBuyFromSTO = 0; uint8 added; IDataStore dataStore = IDataStore(getDataStore()); - (,,,,added) = _kycValues(dataStore.getBytes(_getKey(WHITELIST, _investor))); + bytes memory _whitelistData = dataStore.getBytes(_getKey(WHITELIST, _investor)); + if (_whitelistData.length > 0) { + (,,,,added) = _kycValues(_whitelistData); + } if (_canBuyFromSTO) { canBuyFromSTO = 1; } if (added == uint8(0)) { dataStore.insertAddress(INVESTORS_ARRAY, _investor); } + //whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); bytes memory _data = abi.encode(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); dataStore.setBytes(_getKey(WHITELIST, _investor), _data); diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 50bf3a6bf..52d60366a 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -50,7 +50,6 @@ contract GeneralTransferManagerFactory is ModuleFactory { GeneralTransferManagerProxy generalTransferManager = new GeneralTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); - IBoot(address(generalTransferManager)).initialize(); return address(generalTransferManager); } @@ -58,8 +57,9 @@ contract GeneralTransferManagerFactory is ModuleFactory { * @notice Type of the Module factory */ function getTypes() external view returns(uint8[] memory) { - uint8[] memory res = new uint8[](1); + uint8[] memory res = new uint8[](2); res[0] = 2; + res[1] = 6; return res; } diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index 7184a57d2..6e804062b 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -13,7 +13,7 @@ contract GeneralTransferManagerStorage { bytes32 public constant ALLOWALLTRANSFERS = "ALLOW_ALL_TRANFERS"; bytes32 public constant ALLOWALLWHITELISTTRANSFERS = "ALLOW_ALL_WHITELIST_TRANSFERS"; bytes32 public constant ALLOWALLWHITELISTISSUANCES = "ALLOW_ALL_WHITELIST_ISSUANCES"; - bytes32 public constant ALLOWALLBURNTRANSFERS = "ALLOWALLBURNTRANSFERS"; + bytes32 public constant ALLOWALLBURNTRANSFERS = "ALLOW_ALL_BURN_TRANSFERS"; bytes32 public constant DEFAULTS = "DEFAULTS"; // Data Structure of GTM diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index 8c78c04ff..ba97256a2 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -40,9 +40,9 @@ contract STFactory is ISTFactory { _tokenDetails, _polymathRegistry ); - newSecurityToken.addModule(transferManagerFactory, "", 0, 0); //NB When dataStore is generated, the security token address is automatically set via the constructor in DataStoreProxy. newSecurityToken.changeDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); + newSecurityToken.addModule(transferManagerFactory, "", 0, 0); newSecurityToken.transferOwnership(_issuer); return address(newSecurityToken); } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 7e7e14ba2..8e3115589 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -1,6 +1,7 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/Math.sol"; +import "../interfaces/IBoot.sol"; import "../interfaces/IPoly.sol"; import "../interfaces/IModule.sol"; import "../interfaces/IModuleFactory.sol"; @@ -263,6 +264,15 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater _label ); names[moduleName].push(module); + if (Util.getSig(_data) == "") { + IBoot(module).initialize(); + } else { + require(Util.getSig(_data) == IBoot(module).getInitFunction(), "Provided data is not valid"); + bool success; + /*solium-disable-next-line security/no-low-level-calls*/ + (success, ) = module.call(_data); + require(success, "Unsuccessful call"); + } //Emit log event /*solium-disable-next-line security/no-block-members*/ emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label, now); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 03c22b23f..9109c9d1f 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -169,7 +169,6 @@ contract("GeneralTransferManager", async (accounts) => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); 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[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); @@ -203,11 +202,30 @@ contract("GeneralTransferManager", async (accounts) => { }); it("Should whitelist the affiliates before the STO attached", async () => { + console.log(`Estimate gas of one Whitelist: + ${await I_GeneralTransferManager.modifyWhitelist.estimateGas( + account_affiliates1, + currentTime + currentTime.add(new BN(duration.days(30))), + currentTime + currentTime.add(new BN(duration.days(90))), + currentTime + currentTime.add(new BN(duration.days(965))), + false, + { + from: account_issuer + } + )}` + ); + let fromTime1 = currentTime + currentTime.add(new BN(duration.days(30))); + let fromTime2 = currentTime.add(new BN(duration.days(30))); + let toTime1 = currentTime + currentTime.add(new BN(duration.days(90))); + let toTime2 = currentTime.add(new BN(duration.days(90))); + let expiryTime1 = currentTime + currentTime.add(new BN(duration.days(965))); + let expiryTime2 = currentTime.add(new BN(duration.days(365))); + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( [account_affiliates1, account_affiliates2], - [currentTime + currentTime.add(new BN(duration.days(30))), currentTime.add(new BN(duration.days(30)))], - [currentTime + currentTime.add(new BN(duration.days(90))), currentTime.add(new BN(duration.days(90)))], - [currentTime + currentTime.add(new BN(duration.days(965))), currentTime.add(new BN(duration.days(365)))], + [fromTime1, fromTime2], + [toTime1, toTime2], + [expiryTime1, expiryTime2], [false, false], { from: account_issuer, @@ -218,735 +236,743 @@ contract("GeneralTransferManager", async (accounts) => { 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])); + let data = await I_GeneralTransferManager.getInvestorsData.call([account_affiliates1, account_affiliates2]); + // assert.equal(data[0][0].toString(), fromTime1); + // assert.equal(data[0][1].toString(), fromTime2); + // assert.equal(data[1][0].toString(), toTime1); + // assert.equal(data[1][1].toString(), toTime2); + // assert.equal(data[2][0].toString(), expiryTime1); + // assert.equal(data[2][1].toString(), expiryTime2); + // assert.isFalse(data[3][0]); + // assert.isFalse(data[3][1]); }); it("Should whitelist lots of addresses and check gas", async () => { let mockInvestors = []; - for (let i = 0; i < 50; i++) { + for (let i = 0; i < 45; i++) { mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0, 42 - i.toString().length) + i.toString()); } - let times = range1(50); - let bools = rangeB(50); + let times = range1(45); + let bools = rangeB(45); 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); + console.log("Multi Whitelist x 45: " + 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 () => { - await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { - from: account_issuer, - gas: 6000000 - }); - assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).div(new BN(10).pow(new BN(18))).toNumber(), 100); - assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).div(new BN(10).pow(new BN(18))).toNumber(), 100); - }); - - it("Should successfully attach the STO factory with the security token -- failed because of no tokens", async () => { - let bytesSTO = encodeModuleCall(STOParameters, [ - await latestTime() + duration.seconds(1000), - await latestTime() + duration.days(40), - cap, - someString - ]); - await catchRevert( - I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { from: token_owner }) - ); - }); - - it("Should successfully attach the STO factory with the security token", async () => { - let snap_id = await takeSnapshot(); - let bytesSTO = encodeModuleCall(STOParameters, [ - await latestTime() + duration.seconds(1000), - await latestTime() + duration.days(40), - cap, - someString - ]); - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { - from: token_owner - }); - assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), - "DummySTO", - "DummySTOFactory module was not added" - ); - I_DummySTO = await DummySTO.at(tx.logs[3].args._module); - await revertToSnapshot(snap_id); - }); - - it("Should successfully attach the STO factory with the security token - invalid data", async () => { - let bytesSTO = encodeModuleCall(["uint256", "string"], [await latestTime() + duration.seconds(1000), someString]); - await catchRevert(I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); - }); - - it("Should successfully attach the STO factory with the security token", async () => { - let bytesSTO = encodeModuleCall(STOParameters, [ - await latestTime() + duration.seconds(1000), - await latestTime() + duration.days(40), - cap, - someString - ]); - const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, new BN(0), new BN(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 = await 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, new BN(0), new BN(0), new BN(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 = await 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 () => { - await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - }); - - it("Should Buy the tokens", async () => { - // Add the Investor in to the whitelist - - let tx = await I_GeneralTransferManager.modifyWhitelist( - account_investor1, - currentTime, - currentTime, - currentTime.add(new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - }); - - it("Should fail in buying the token from the STO", async () => { - await catchRevert(I_DummySTO.generateTokens(account_affiliates1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - }); - - it("Should fail in buying the tokens from the STO -- because amount is 0", async () => { - await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(0), { from: token_owner })); - }); - - it("Should fail in buying the tokens from the STO -- because STO is paused", async () => { - await I_DummySTO.pause({ from: account_issuer }); - await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // Reverting the changes releated to pause - await I_DummySTO.unpause({ from: account_issuer }); - }); - - it("Should buy more tokens from the STO to investor1", async () => { - await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); - }); - - it("Should fail in investing the money in STO -- expiry limit reached", async () => { - await increaseTime(duration.days(10)); - - await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - }); - }); - - 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, new BN(0), new BN(0), currentTime.add(new BN(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, - currentTime, - currentTime, - currentTime.add(new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - }); - - it("Add a from default and check transfers are disabled then enabled in the future", async () => { - let tx = await I_GeneralTransferManager.changeDefaults(currentTime.add(new BN(duration.days(12))), new BN(0), { from: token_owner }); - await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); - await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); - await increaseTime(duration.days(5)); - await I_SecurityToken.transfer(account_investor2, new BN(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, currentTime.add(new BN(duration.days(16))), { from: token_owner }); - await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); - await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - await increaseTime(duration.days(2)); - await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); - // revert changes - await I_GeneralTransferManager.modifyWhitelist(account_investor2, new BN(0), new BN(0), new BN(0), false, { - from: account_issuer, - gas: 6000000 - }); - await I_GeneralTransferManager.changeDefaults(0, new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - }); - - it("Should provide the permission and change the signing address", async () => { - let log = await I_GeneralPermissionManager.addDelegate(account_delegate, web3.utils.fromAscii("My details"), { from: token_owner }); - assert.equal(log.logs[0].args._delegate, account_delegate); - - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { - from: token_owner - }); - - assert.isTrue( - await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS")) - ); - console.log(JSON.stringify(signer)); - let tx = await I_GeneralTransferManager.changeSigningAddress(signer.address, { from: account_delegate }); - assert.equal(tx.logs[0].args._signingAddress, signer.address); - }); - - 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 = await latestTime(); - let validTo = await latestTime() + duration.days(5); - let nonce = 5; - const sig = getSignGTMData( - account_investor2, - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - nonce, - signer.privateKey - ); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - nonce, - sig, - { - from: account_investor2, - gas: 6000000 - } - ) - ); - }); - - 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 = await latestTime() - 100; - let validTo = await latestTime() - 1; - let nonce = 5; - const sig = getSignGTMData( - I_GeneralTransferManager.address, - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - nonce, - signer.privateKey - ); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - nonce, - sig, - { - from: account_investor2, - gas: 6000000 - } - ) - ); - }); - - 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 = await latestTime(); - let validTo = await latestTime() + 60 * 60; - let nonce = 5; - const sig = getSignGTMData( - account_investor2, - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - nonce, - "2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200" - ); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - fromTime, - toTime, - expiryTime, - true, - validFrom, - validTo, - nonce, - sig, - { - from: account_investor2, - gas: 6000000 - } - ) - ); - }); - - it("Should Buy the tokens with signers signature", async () => { - // Add the Investor in to the whitelist - //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - let validFrom = await latestTime(); - let validTo = await latestTime() + duration.days(5); - let nonce = 5; - const sig = getSignGTMData( - I_GeneralTransferManager.address, - account_investor2, - currentTime.toNumber(), - currentTime.add(new BN(duration.days(100))).toNumber(), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - nonce, - signer.privateKey - ); - - let tx = await I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - currentTime.toNumber(), - currentTime.add(new BN(duration.days(100))).toNumber(), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - nonce, - sig, - { - 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - - assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - }); - - 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 = await latestTime(); - let validTo = await latestTime() + duration.days(5); - let nonce = 5; - const sig = getSignGTMData( - I_GeneralTransferManager.address, - account_investor2, - currentTime.toNumber(), - currentTime.add(new BN(duration.days(100))).toNumber(), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - nonce, - signer.privateKey - ); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - currentTime.toNumber(), - currentTime.add(new BN(duration.days(100))).toNumber(), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - nonce, - sig, - { - from: account_investor2, - gas: 6000000 - } - ) - ); - }); - - it("Should sign with token owner key", async () => { - // Add the Investor in to the whitelist - //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - let validFrom = await latestTime(); - let validTo = await latestTime() + duration.days(5); - let nonce = 6; - const sig = getSignGTMData( - I_GeneralTransferManager.address, - account_investor2, - currentTime.toNumber(), - currentTime.add(new BN(duration.days(100))).toNumber(), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - nonce, - "0x" + token_owner_pk - ); - - await I_GeneralTransferManager.modifyWhitelistSigned( - account_investor2, - currentTime.toNumber(), - currentTime.add(new BN(duration.days(100))).toNumber(), - expiryTime + duration.days(200), - true, - validFrom, - validTo, - nonce, - sig, - { - from: account_investor2, - gas: 6000000 - } - ) - - }); - - it("Should fail in changing the signing address", async () => { - await catchRevert(I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_investor4 })); - }); - - 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 fail to pull fees as no budget set", async () => { - await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_polymath })); - }); - - it("Should set a budget for the GeneralTransferManager", async () => { - await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, new BN(10).pow(new BN(19)), true, { from: token_owner }); - - await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - await I_PolyToken.getTokens(new BN(10).pow(new BN(19)), token_owner); - await I_PolyToken.transfer(I_SecurityToken.address, new BN(10).pow(new BN(19)), { from: token_owner }); - }); - - it("Factory owner should pull fees - fails as not permissioned by issuer", async () => { - await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate })); - }); - - it("Factory owner should pull fees", async () => { - await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FEE_ADMIN"), true, { - from: token_owner - }); - let balanceBefore = await I_PolyToken.balanceOf(account_polymath); - await I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate }); - let balanceAfter = await I_PolyToken.balanceOf(account_polymath); - assert.equal(balanceBefore.add(new BN(web3.utils.toWei("1", "ether"))).toString(), balanceAfter.toString(), "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 }); - await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); - }); - - 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 = await latestTime(); - let toTime = await latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime, toTime], - [expiryTime, expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ) - ); - }); - - it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - let fromTime = await latestTime(); - let toTime = await latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime], - [toTime, toTime], - [expiryTime, expiryTime], - [1, 1], - { - from: account_delegate, - gas: 6000000 - } - ) - ); - }); - - it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - let fromTime = await latestTime(); - let toTime = await latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime], - [expiryTime, expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ) - ); - }); - - it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - let fromTime = await latestTime(); - let toTime = await latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - - await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( - [account_investor3, account_investor4], - [fromTime, fromTime], - [toTime, toTime], - [expiryTime], - [true, true], - { - from: account_delegate, - gas: 6000000 - } - ) - ); - }); - - it("Should successfully add the investors in whitelist", async () => { - let fromTime = await latestTime(); - let toTime = await latestTime() + duration.days(20); - let expiryTime = toTime + duration.days(10); - - 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.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, ""), - "GeneralTransferManager", - "Wrong Module added" - ); - assert.equal( - await I_GeneralTransferManagerFactory.description.call(), - "Manage transfers using a time based whitelist", - "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.", - "Wrong Module added" - ); - assert.equal(await I_GeneralTransferManagerFactory.version.call(), "2.1.0"); - }); - - 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.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.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"); - }); - - 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"); - }); - - it("Should get the version of factory", async () => { - let version = await I_DummySTOFactory.version.call(); - assert.equal(version, "1.0.0"); - }); + // it("Should mint the tokens to the affiliates", async () => { + // await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { + // from: account_issuer, + // gas: 6000000 + // }); + // assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).div(new BN(10).pow(new BN(18))).toNumber(), 100); + // assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).div(new BN(10).pow(new BN(18))).toNumber(), 100); + // }); + + // it("Should successfully attach the STO factory with the security token -- failed because of no tokens", async () => { + // let bytesSTO = encodeModuleCall(STOParameters, [ + // await latestTime() + duration.seconds(1000), + // await latestTime() + duration.days(40), + // cap, + // someString + // ]); + // await catchRevert( + // I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { from: token_owner }) + // ); + // }); + + // it("Should successfully attach the STO factory with the security token", async () => { + // let snap_id = await takeSnapshot(); + // let bytesSTO = encodeModuleCall(STOParameters, [ + // await latestTime() + duration.seconds(1000), + // await latestTime() + duration.days(40), + // cap, + // someString + // ]); + // await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + // const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + // from: token_owner + // }); + // assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); + // assert.equal( + // web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), + // "DummySTO", + // "DummySTOFactory module was not added" + // ); + // I_DummySTO = await DummySTO.at(tx.logs[3].args._module); + // await revertToSnapshot(snap_id); + // }); + + // it("Should successfully attach the STO factory with the security token - invalid data", async () => { + // let bytesSTO = encodeModuleCall(["uint256", "string"], [await latestTime() + duration.seconds(1000), someString]); + // await catchRevert(I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); + // }); + + // it("Should successfully attach the STO factory with the security token", async () => { + // let bytesSTO = encodeModuleCall(STOParameters, [ + // await latestTime() + duration.seconds(1000), + // await latestTime() + duration.days(40), + // cap, + // someString + // ]); + // const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, new BN(0), new BN(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 = await 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, new BN(0), new BN(0), new BN(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 = await GeneralPermissionManager.at(tx.logs[2].args._module); + // }); }); - 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)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); - }); - - it("Should get the raised amount of poly", async () => { - assert.equal((await I_DummySTO.getRaised.call(1)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); - }); - - it("Should get the investors", async () => { - assert.equal((await I_DummySTO.getNumberInvestors.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"); - }); - - it("Should get the amount of tokens sold", async () => { - assert.equal(await I_DummySTO.getTokensSold.call(), 0); - }); - }); + // describe("Buy tokens using on-chain whitelist", async () => { + // it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { + // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // }); + + // it("Should Buy the tokens", async () => { + // // Add the Investor in to the whitelist + + // let tx = await I_GeneralTransferManager.modifyWhitelist( + // account_investor1, + // currentTime, + // currentTime, + // currentTime.add(new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + + // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + // }); + + // it("Should fail in buying the token from the STO", async () => { + // await catchRevert(I_DummySTO.generateTokens(account_affiliates1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // }); + + // it("Should fail in buying the tokens from the STO -- because amount is 0", async () => { + // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(0), { from: token_owner })); + // }); + + // it("Should fail in buying the tokens from the STO -- because STO is paused", async () => { + // await I_DummySTO.pause({ from: account_issuer }); + // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // // Reverting the changes releated to pause + // await I_DummySTO.unpause({ from: account_issuer }); + // }); + + // it("Should buy more tokens from the STO to investor1", async () => { + // await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + // }); + + // it("Should fail in investing the money in STO -- expiry limit reached", async () => { + // await increaseTime(duration.days(10)); + + // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // }); + // }); + + // 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, new BN(0), new BN(0), currentTime.add(new BN(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, + // currentTime, + // currentTime, + // currentTime.add(new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + // }); + + // it("Add a from default and check transfers are disabled then enabled in the future", async () => { + // let tx = await I_GeneralTransferManager.changeDefaults(currentTime.add(new BN(duration.days(12))), new BN(0), { from: token_owner }); + // await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); + // await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); + // await increaseTime(duration.days(5)); + // await I_SecurityToken.transfer(account_investor2, new BN(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, currentTime.add(new BN(duration.days(16))), { from: token_owner }); + // await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); + // await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + // await increaseTime(duration.days(2)); + // await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); + // // revert changes + // await I_GeneralTransferManager.modifyWhitelist(account_investor2, new BN(0), new BN(0), new BN(0), false, { + // from: account_issuer, + // gas: 6000000 + // }); + // await I_GeneralTransferManager.changeDefaults(0, new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // }); + + // it("Should provide the permission and change the signing address", async () => { + // let log = await I_GeneralPermissionManager.addDelegate(account_delegate, web3.utils.fromAscii("My details"), { from: token_owner }); + // assert.equal(log.logs[0].args._delegate, account_delegate); + + // await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { + // from: token_owner + // }); + + // assert.isTrue( + // await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS")) + // ); + // console.log(JSON.stringify(signer)); + // let tx = await I_GeneralTransferManager.changeSigningAddress(signer.address, { from: account_delegate }); + // assert.equal(tx.logs[0].args._signingAddress, signer.address); + // }); + + // 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 = await latestTime(); + // let validTo = await latestTime() + duration.days(5); + // let nonce = 5; + // const sig = getSignGTMData( + // account_investor2, + // account_investor2, + // fromTime, + // toTime, + // expiryTime, + // true, + // validFrom, + // validTo, + // nonce, + // signer.privateKey + // ); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistSigned( + // account_investor2, + // fromTime, + // toTime, + // expiryTime, + // true, + // validFrom, + // validTo, + // nonce, + // sig, + // { + // from: account_investor2, + // gas: 6000000 + // } + // ) + // ); + // }); + + // 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 = await latestTime() - 100; + // let validTo = await latestTime() - 1; + // let nonce = 5; + // const sig = getSignGTMData( + // I_GeneralTransferManager.address, + // account_investor2, + // fromTime, + // toTime, + // expiryTime, + // true, + // validFrom, + // validTo, + // nonce, + // signer.privateKey + // ); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistSigned( + // account_investor2, + // fromTime, + // toTime, + // expiryTime, + // true, + // validFrom, + // validTo, + // nonce, + // sig, + // { + // from: account_investor2, + // gas: 6000000 + // } + // ) + // ); + // }); + + // 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 = await latestTime(); + // let validTo = await latestTime() + 60 * 60; + // let nonce = 5; + // const sig = getSignGTMData( + // account_investor2, + // account_investor2, + // fromTime, + // toTime, + // expiryTime, + // true, + // validFrom, + // validTo, + // nonce, + // "2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200" + // ); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistSigned( + // account_investor2, + // fromTime, + // toTime, + // expiryTime, + // true, + // validFrom, + // validTo, + // nonce, + // sig, + // { + // from: account_investor2, + // gas: 6000000 + // } + // ) + // ); + // }); + + // it("Should Buy the tokens with signers signature", async () => { + // // Add the Investor in to the whitelist + // //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + // let validFrom = await latestTime(); + // let validTo = await latestTime() + duration.days(5); + // let nonce = 5; + // const sig = getSignGTMData( + // I_GeneralTransferManager.address, + // account_investor2, + // currentTime.toNumber(), + // currentTime.add(new BN(duration.days(100))).toNumber(), + // expiryTime + duration.days(200), + // true, + // validFrom, + // validTo, + // nonce, + // signer.privateKey + // ); + + // let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + // account_investor2, + // currentTime.toNumber(), + // currentTime.add(new BN(duration.days(100))).toNumber(), + // expiryTime + duration.days(200), + // true, + // validFrom, + // validTo, + // nonce, + // sig, + // { + // 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + + // assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + // }); + + // 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 = await latestTime(); + // let validTo = await latestTime() + duration.days(5); + // let nonce = 5; + // const sig = getSignGTMData( + // I_GeneralTransferManager.address, + // account_investor2, + // currentTime.toNumber(), + // currentTime.add(new BN(duration.days(100))).toNumber(), + // expiryTime + duration.days(200), + // true, + // validFrom, + // validTo, + // nonce, + // signer.privateKey + // ); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistSigned( + // account_investor2, + // currentTime.toNumber(), + // currentTime.add(new BN(duration.days(100))).toNumber(), + // expiryTime + duration.days(200), + // true, + // validFrom, + // validTo, + // nonce, + // sig, + // { + // from: account_investor2, + // gas: 6000000 + // } + // ) + // ); + // }); + + // it("Should sign with token owner key", async () => { + // // Add the Investor in to the whitelist + // //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + // let validFrom = await latestTime(); + // let validTo = await latestTime() + duration.days(5); + // let nonce = 6; + // const sig = getSignGTMData( + // I_GeneralTransferManager.address, + // account_investor2, + // currentTime.toNumber(), + // currentTime.add(new BN(duration.days(100))).toNumber(), + // expiryTime + duration.days(200), + // true, + // validFrom, + // validTo, + // nonce, + // "0x" + token_owner_pk + // ); + + // await I_GeneralTransferManager.modifyWhitelistSigned( + // account_investor2, + // currentTime.toNumber(), + // currentTime.add(new BN(duration.days(100))).toNumber(), + // expiryTime + duration.days(200), + // true, + // validFrom, + // validTo, + // nonce, + // sig, + // { + // from: account_investor2, + // gas: 6000000 + // } + // ) + + // }); + + // it("Should fail in changing the signing address", async () => { + // await catchRevert(I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_investor4 })); + // }); + + // 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 fail to pull fees as no budget set", async () => { + // await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_polymath })); + // }); + + // it("Should set a budget for the GeneralTransferManager", async () => { + // await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, new BN(10).pow(new BN(19)), true, { from: token_owner }); + + // await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // await I_PolyToken.getTokens(new BN(10).pow(new BN(19)), token_owner); + // await I_PolyToken.transfer(I_SecurityToken.address, new BN(10).pow(new BN(19)), { from: token_owner }); + // }); + + // it("Factory owner should pull fees - fails as not permissioned by issuer", async () => { + // await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate })); + // }); + + // it("Factory owner should pull fees", async () => { + // await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FEE_ADMIN"), true, { + // from: token_owner + // }); + // let balanceBefore = await I_PolyToken.balanceOf(account_polymath); + // await I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate }); + // let balanceAfter = await I_PolyToken.balanceOf(account_polymath); + // assert.equal(balanceBefore.add(new BN(web3.utils.toWei("1", "ether"))).toString(), balanceAfter.toString(), "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 }); + // await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); + // }); + + // 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 = await latestTime(); + // let toTime = await latestTime() + duration.days(20); + // let expiryTime = toTime + duration.days(10); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistMulti( + // [account_investor3, account_investor4], + // [fromTime, fromTime], + // [toTime, toTime], + // [expiryTime, expiryTime], + // [true, true], + // { + // from: account_delegate, + // gas: 6000000 + // } + // ) + // ); + // }); + + // it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { + // let fromTime = await latestTime(); + // let toTime = await latestTime() + duration.days(20); + // let expiryTime = toTime + duration.days(10); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistMulti( + // [account_investor3, account_investor4], + // [fromTime], + // [toTime, toTime], + // [expiryTime, expiryTime], + // [1, 1], + // { + // from: account_delegate, + // gas: 6000000 + // } + // ) + // ); + // }); + + // it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { + // let fromTime = await latestTime(); + // let toTime = await latestTime() + duration.days(20); + // let expiryTime = toTime + duration.days(10); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistMulti( + // [account_investor3, account_investor4], + // [fromTime, fromTime], + // [toTime], + // [expiryTime, expiryTime], + // [true, true], + // { + // from: account_delegate, + // gas: 6000000 + // } + // ) + // ); + // }); + + // it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { + // let fromTime = await latestTime(); + // let toTime = await latestTime() + duration.days(20); + // let expiryTime = toTime + duration.days(10); + + // await catchRevert( + // I_GeneralTransferManager.modifyWhitelistMulti( + // [account_investor3, account_investor4], + // [fromTime, fromTime], + // [toTime, toTime], + // [expiryTime], + // [true, true], + // { + // from: account_delegate, + // gas: 6000000 + // } + // ) + // ); + // }); + + // it("Should successfully add the investors in whitelist", async () => { + // let fromTime = await latestTime(); + // let toTime = await latestTime() + duration.days(20); + // let expiryTime = toTime + duration.days(10); + + // 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.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, ""), + // "GeneralTransferManager", + // "Wrong Module added" + // ); + // assert.equal( + // await I_GeneralTransferManagerFactory.description.call(), + // "Manage transfers using a time based whitelist", + // "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.", + // "Wrong Module added" + // ); + // assert.equal(await I_GeneralTransferManagerFactory.version.call(), "2.1.0"); + // }); + + // 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.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.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"); + // }); + + // 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"); + // }); + + // it("Should get the version of factory", async () => { + // let version = await I_DummySTOFactory.version.call(); + // assert.equal(version, "1.0.0"); + // }); + // }); + + // 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)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + // }); + + // it("Should get the raised amount of poly", async () => { + // assert.equal((await I_DummySTO.getRaised.call(1)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + // }); + + // it("Should get the investors", async () => { + // assert.equal((await I_DummySTO.getNumberInvestors.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"); + // }); + + // it("Should get the amount of tokens sold", async () => { + // assert.equal(await I_DummySTO.getTokensSold.call(), 0); + // }); + // }); }); function range1(i) { From f9651163df8e7df0f52cc62bb4f38ce1dd350d53 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 4 Feb 2019 14:18:22 +0530 Subject: [PATCH 092/119] typo fix --- contracts/modules/Module.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 95a73f182..bcce7781c 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -2,7 +2,7 @@ pragma solidity ^0.5.0; import "./ModuleStorage.sol"; import "../interfaces/IModule.sol"; -import "../interfaces/IDatastore.sol"; +import "../interfaces/IDataStore.sol"; import "../interfaces/ISecurityToken.sol"; import "../interfaces/ICheckPermission.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; From 5f8272ed003fb12ff99fda5a9c64c71bd6823a4b Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 4 Feb 2019 21:02:46 +0530 Subject: [PATCH 093/119] fixing the tests --- contracts/libraries/VersionUtils.sol | 20 ++ .../GeneralPermissionManager.sol | 2 + contracts/modules/STO/DummySTO.sol | 4 +- .../GeneralTransferManager.sol | 86 +++-- test/h_general_transfer_manager.js | 299 ++++++++++-------- 5 files changed, 243 insertions(+), 168 deletions(-) diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 645e183b4..22c87b2dd 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -106,4 +106,24 @@ library VersionUtils { return _unpackVersion; } + + /** + * @notice Used to packed the KYC data + */ + function packKYC(uint64 _a, uint64 _b, uint64 _c, uint8 _d, uint8 _e) internal pure returns(uint256) { + return (uint256(_a) << 192) | (uint256(_b) << 128) | (uint256(_c) << 64) | (uint256(_d) << 16) | uint256(_e); + } + + /** + * @notice Used to convert packed data into KYC data + * @param _packedVersion Packed data + */ + function unpackKYC(uint256 _packedVersion) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added) { + fromTime = uint64(_packedVersion >> 192); + toTime = uint64(_packedVersion >> 128); + expiryTime = uint64(_packedVersion >> 64); + canBuy = uint8(_packedVersion >> 16); + added = uint8(_packedVersion); + } + } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 6ce855897..9281145f2 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -27,6 +27,8 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio return bytes4(0); } + function initialize() public {} + /** * @notice Used to check the permission on delegate corresponds to module contract address * @param _delegate Ethereum address of the delegate diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index e264685a7..502e88ba4 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -25,7 +25,7 @@ contract DummySTO is DummySTOStorage, STO { * @param _cap Maximum No. of tokens for sale * @param _someString Any string that contails the details */ - function configure(uint256 _startTime, uint256 _endTime, uint256 _cap, string memory _someString) public onlyFactory { + function configure(uint256 _startTime, uint256 _endTime, uint256 _cap, string memory _someString) public onlyST { startTime = _startTime; endTime = _endTime; cap = _cap; @@ -36,7 +36,7 @@ contract DummySTO is DummySTOStorage, STO { * @notice This function returns the signature of configure function */ function getInitFunction() public pure returns(bytes4) { - return bytes4(keccak256("configure(uint256,uint256,uint256,string)")); + return this.configure.selector; } /** diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 432e1282a..1da18cf30 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -1,6 +1,8 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; +import "../../libraries/Encoder.sol"; +import "../../libraries/VersionUtils.sol"; import "../../storage/GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; @@ -25,7 +27,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage // 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(uint256 _defaultFromTime, uint256 _defaultToTime); // _fromTime is the time from which the _investor can send tokens // _toTime is the time from which the _investor can receive tokens @@ -72,9 +74,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _defaultFromTime default for zero fromTime * @param _defaultToTime default for zero toTime */ - function changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { - bytes memory _data = abi.encode(_defaultFromTime, _defaultToTime); - IDataStore(getDataStore()).setBytes(DEFAULTS, _data); + function changeDefaults(uint256 _defaultFromTime, uint256 _defaultToTime) public withPerm(FLAGS) { + IDataStore(getDataStore()).setUint256(Encoder.getKey("fromTime", DEFAULTS), _defaultFromTime); + IDataStore(getDataStore()).setUint256(Encoder.getKey("toTime", DEFAULTS), _defaultFromTime); emit ChangeDefaults(_defaultFromTime, _defaultToTime); } @@ -172,7 +174,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return Result.VALID; } - (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValues(_from, _to); + (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValuesToUser(_from, _to); if (dataStore.getBool(ALLOWALLWHITELISTTRANSFERS)) { //Anyone on the whitelist can transfer, regardless of time @@ -232,23 +234,18 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage */ function _modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO) internal { require(_investor != address(0), "Invalid investor"); - uint8 canBuyFromSTO = 0; uint8 added; + uint8 canBuyFromSTO = 0; IDataStore dataStore = IDataStore(getDataStore()); - bytes memory _whitelistData = dataStore.getBytes(_getKey(WHITELIST, _investor)); - if (_whitelistData.length > 0) { - (,,,,added) = _kycValues(_whitelistData); - } - if (_canBuyFromSTO) { - canBuyFromSTO = 1; - } + (,,,,added) = _getValues(_investor); if (added == uint8(0)) { dataStore.insertAddress(INVESTORS_ARRAY, _investor); } - - //whitelist[_investor] = TimeRestriction(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); - bytes memory _data = abi.encode(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); - dataStore.setBytes(_getKey(WHITELIST, _investor), _data); + if (_canBuyFromSTO) { + canBuyFromSTO = 1; + } + uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + dataStore.setUint256(_getKey(WHITELIST, _investor), _data); emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } @@ -349,28 +346,28 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage function _adjustTimes(uint64 _fromTime, uint64 _toTime) internal view returns(uint64, uint64) { uint64 adjustedFromTime = _fromTime; uint64 adjustedToTime = _toTime; - (uint64 defaultFromTime, uint64 defaultToTime) = abi.decode(IDataStore(getDataStore()).getBytes(DEFAULTS), (uint64, uint64)); if (_fromTime == 0) { - adjustedFromTime = defaultFromTime; + adjustedFromTime = uint64(IDataStore(getDataStore()).getUint256(Encoder.getKey("fromTime", DEFAULTS))); } if (_toTime == 0) { - adjustedToTime = defaultToTime; + adjustedToTime = uint64(IDataStore(getDataStore()).getUint256(Encoder.getKey("toTime", DEFAULTS))); } return (adjustedFromTime, adjustedToTime); } - function _kycValues(bytes memory _data) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added) { - return abi.decode(_data, (uint64, uint64, uint64, uint8, uint8)); + function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function _getValues(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry ) { + function _getValues(address _investor) internal view returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuyFromSTO, uint8 added) { IDataStore dataStore = IDataStore(getDataStore()); - (fromTime,, fromExpiry, canBuyFromSTO,) = _kycValues(dataStore.getBytes(_getKey(WHITELIST, _from))); - (, toTime, toExpiry,,) = _kycValues(dataStore.getBytes(_getKey(WHITELIST, _to))); + uint256 _whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); + (fromTime, toTime, expiryTime, canBuyFromSTO, added) = VersionUtils.unpackKYC(_whitelistData); } - function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(_key1, _key2))); + function _getValuesToUser(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry ) { + (fromTime,, fromExpiry, canBuyFromSTO,) = _getValues(_from); + (, toTime, toExpiry,,) = _getValues(_to); } /** @@ -419,9 +416,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage bool[] memory canBuyFromSTOs = new bool[](_investors.length); for (uint256 i = 0; i < _investors.length; i++) { uint8 canBuyFromSTO; - (fromTimes[i], toTimes[i], expiryTimes[i], canBuyFromSTO,) = _kycValues( - IDataStore(getDataStore()).getBytes(_getKey(WHITELIST, _investors[i])) - ); + (fromTimes[i], toTimes[i], expiryTimes[i], canBuyFromSTO,) = _getValues(_investors[i]); if (canBuyFromSTO == 0) { canBuyFromSTOs[i] = false; } else { @@ -431,6 +426,37 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs); } + function getSigningAddress() external view returns(address) { + return IDataStore(getDataStore()).getAddress(SIGNING_ADD); + } + + function getIssuanceAddress() external view returns(address) { + return IDataStore(getDataStore()).getAddress(ISSUANCE_ADD); + } + + function allowAllTransfers() external view returns(bool) { + return IDataStore(getDataStore()).getBool(ALLOWALLTRANSFERS); + } + + function allowAllWhitelistTransfers() external view returns(bool) { + return IDataStore(getDataStore()).getBool(ALLOWALLWHITELISTTRANSFERS); + } + + function allowAllWhitelistIssuances() external view returns(bool) { + return IDataStore(getDataStore()).getBool(ALLOWALLWHITELISTISSUANCES); + } + + function allowAllBurnTransfers() external view returns(bool) { + return IDataStore(getDataStore()).getBool(ALLOWALLBURNTRANSFERS); + } + + function getDefaultTimes() external view returns(uint256, uint256) { + return( + IDataStore(getDataStore()).getUint256(Encoder.getKey("fromTime", DEFAULTS)), + IDataStore(getDataStore()).getUint256(Encoder.getKey("toTime", DEFAULTS)) + ); + } + /** * @notice Return the permissions flag that are associated with general trnasfer manager */ diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 9109c9d1f..f32240ca5 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -237,173 +237,200 @@ contract("GeneralTransferManager", async (accounts) => { assert.deepEqual(await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2]); console.log(await I_GeneralTransferManager.getAllInvestorsData.call()); let data = await I_GeneralTransferManager.getInvestorsData.call([account_affiliates1, account_affiliates2]); - // assert.equal(data[0][0].toString(), fromTime1); - // assert.equal(data[0][1].toString(), fromTime2); - // assert.equal(data[1][0].toString(), toTime1); - // assert.equal(data[1][1].toString(), toTime2); - // assert.equal(data[2][0].toString(), expiryTime1); - // assert.equal(data[2][1].toString(), expiryTime2); - // assert.isFalse(data[3][0]); - // assert.isFalse(data[3][1]); + assert.equal(data[0][0].toString(), fromTime1); + assert.equal(data[0][1].toString(), fromTime2); + assert.equal(data[1][0].toString(), toTime1); + assert.equal(data[1][1].toString(), toTime2); + assert.equal(data[2][0].toString(), expiryTime1); + assert.equal(data[2][1].toString(), expiryTime2); + assert.isFalse(data[3][0]); + assert.isFalse(data[3][1]); }); it("Should whitelist lots of addresses and check gas", async () => { let mockInvestors = []; - for (let i = 0; i < 45; i++) { + for (let i = 0; i < 90; i++) { mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0, 42 - i.toString().length) + i.toString()); } - let times = range1(45); - let bools = rangeB(45); + let times = range1(90); + let bools = rangeB(90); let tx = await I_GeneralTransferManager.modifyWhitelistMulti(mockInvestors, times, times, times, bools, { from: account_issuer, gas: 7900000 }); - console.log("Multi Whitelist x 45: " + tx.receipt.gasUsed); + console.log("Multi Whitelist x 90: " + 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 () => { - // await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { - // from: account_issuer, - // gas: 6000000 - // }); - // assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).div(new BN(10).pow(new BN(18))).toNumber(), 100); - // assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).div(new BN(10).pow(new BN(18))).toNumber(), 100); - // }); - - // it("Should successfully attach the STO factory with the security token -- failed because of no tokens", async () => { - // let bytesSTO = encodeModuleCall(STOParameters, [ - // await latestTime() + duration.seconds(1000), - // await latestTime() + duration.days(40), - // cap, - // someString - // ]); - // await catchRevert( - // I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { from: token_owner }) - // ); - // }); - - // it("Should successfully attach the STO factory with the security token", async () => { - // let snap_id = await takeSnapshot(); - // let bytesSTO = encodeModuleCall(STOParameters, [ - // await latestTime() + duration.seconds(1000), - // await latestTime() + duration.days(40), - // cap, - // someString - // ]); - // await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); - // const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { - // from: token_owner - // }); - // assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); - // assert.equal( - // web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), - // "DummySTO", - // "DummySTOFactory module was not added" - // ); - // I_DummySTO = await DummySTO.at(tx.logs[3].args._module); - // await revertToSnapshot(snap_id); - // }); - - // it("Should successfully attach the STO factory with the security token - invalid data", async () => { - // let bytesSTO = encodeModuleCall(["uint256", "string"], [await latestTime() + duration.seconds(1000), someString]); - // await catchRevert(I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); - // }); - - // it("Should successfully attach the STO factory with the security token", async () => { - // let bytesSTO = encodeModuleCall(STOParameters, [ - // await latestTime() + duration.seconds(1000), - // await latestTime() + duration.days(40), - // cap, - // someString - // ]); - // const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, new BN(0), new BN(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 = await 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, new BN(0), new BN(0), new BN(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 = await GeneralPermissionManager.at(tx.logs[2].args._module); - // }); + it("Should mint the tokens to the affiliates", async () => { + await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { + from: account_issuer, + gas: 6000000 + }); + assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates1)).div(new BN(10).pow(new BN(18))).toNumber(), 100); + assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).div(new BN(10).pow(new BN(18))).toNumber(), 100); + }); + + it("Should successfully attach the STO factory with the security token -- failed because of no tokens", async () => { + let bytesSTO = encodeModuleCall(STOParameters, [ + await latestTime() + duration.seconds(1000), + await latestTime() + duration.days(40), + cap, + someString + ]); + await catchRevert( + I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { from: token_owner }) + ); + }); + + it("Should successfully attach the STO factory with the security token", async () => { + let snap_id = await takeSnapshot(); + let bytesSTO = encodeModuleCall(STOParameters, [ + await latestTime() + duration.seconds(1000), + await latestTime() + duration.days(40), + cap, + someString + ]); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + from: token_owner + }); + assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), + "DummySTO", + "DummySTOFactory module was not added" + ); + I_DummySTO = await DummySTO.at(tx.logs[3].args._module); + await revertToSnapshot(snap_id); + }); + + it("Should successfully attach the STO factory with the security token - invalid data", async () => { + let bytesSTO = encodeModuleCall(["uint256", "string"], [await latestTime() + duration.seconds(1000), someString]); + await catchRevert(I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(0), new BN(0), { from: token_owner })); + }); + + it("Should successfully attach the STO factory with the security token", async () => { + let bytesSTO = encodeModuleCall(STOParameters, [ + await latestTime() + duration.seconds(1000), + await latestTime() + duration.days(40), + cap, + someString + ]); + const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, new BN(0), new BN(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 = await 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, new BN(0), new BN(0), new BN(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 = await 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 () => { - // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // }); + describe("Verify the values of the public variables", async() => { - // it("Should Buy the tokens", async () => { - // // Add the Investor in to the whitelist + it("Should the signing address be 0x", async() => { + assert.equal(await I_GeneralTransferManager.getSigningAddress.call(), address_zero); + }); - // let tx = await I_GeneralTransferManager.modifyWhitelist( - // account_investor1, - // currentTime, - // currentTime, - // currentTime.add(new BN(duration.days(10))), - // true, - // { - // from: account_issuer, - // gas: 6000000 - // } - // ); + it("Should issuance address will be 0x", async() => { + assert.equal(await I_GeneralTransferManager.getIssuanceAddress.call(), address_zero); + }); - // assert.equal( - // tx.logs[0].args._investor.toLowerCase(), - // account_investor1.toLowerCase(), - // "Failed in adding the investor in whitelist" - // ); + it("Should allowAllTransfers be false", async() => { + assert.isFalse(await I_GeneralTransferManager.allowAllTransfers.call()); + }); - // // Jump time - // await increaseTime(5000); + it("Should allowAllWhitelistTransfers be false", async() => { + assert.isFalse(await I_GeneralTransferManager.allowAllWhitelistTransfers.call()); + }); - // // Mint some tokens - // await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + it("Should allowAllWhitelistIssuances be true", async() => { + assert.isTrue(await I_GeneralTransferManager.allowAllWhitelistIssuances.call()); + }); - // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - // }); + it("Should allowAllBurnTransfers be false", async() => { + assert.isFalse(await I_GeneralTransferManager.allowAllBurnTransfers.call()); + }); + }) - // it("Should fail in buying the token from the STO", async () => { - // await catchRevert(I_DummySTO.generateTokens(account_affiliates1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // }); + describe("Buy tokens using on-chain whitelist", async () => { + it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + }); - // it("Should fail in buying the tokens from the STO -- because amount is 0", async () => { - // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(0), { from: token_owner })); - // }); + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist - // it("Should fail in buying the tokens from the STO -- because STO is paused", async () => { - // await I_DummySTO.pause({ from: account_issuer }); - // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // // Reverting the changes releated to pause - // await I_DummySTO.unpause({ from: account_issuer }); - // }); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + currentTime, + currentTime, + currentTime.add(new BN(duration.days(10))), + true, + { + from: account_issuer, + gas: 6000000 + } + ); - // it("Should buy more tokens from the STO to investor1", async () => { - // await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); - // }); + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); - // it("Should fail in investing the money in STO -- expiry limit reached", async () => { - // await increaseTime(duration.days(10)); + // Jump time + await increaseTime(5000); - // await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // }); - // }); + // Mint some tokens + await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + }); + + it("Should fail in buying the token from the STO", async () => { + await catchRevert(I_DummySTO.generateTokens(account_affiliates1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + }); + + it("Should fail in buying the tokens from the STO -- because amount is 0", async () => { + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(0), { from: token_owner })); + }); + + it("Should fail in buying the tokens from the STO -- because STO is paused", async () => { + await I_DummySTO.pause({ from: account_issuer }); + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + // Reverting the changes releated to pause + await I_DummySTO.unpause({ from: account_issuer }); + }); + + it("Should buy more tokens from the STO to investor1", async () => { + await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); + }); + + it("Should fail in investing the money in STO -- expiry limit reached", async () => { + await increaseTime(duration.days(10)); + + await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + }); + }); // describe("Buy tokens using on-chain whitelist and defaults", async () => { // // let snap_id; From 7f893472f56b78593fda1ba1c5a09c29eb68e043 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 5 Feb 2019 11:39:12 +0530 Subject: [PATCH 094/119] Removed test/s_v130_to_v140_upgrade.js --- test/s_v130_to_v140_upgrade.js | 458 --------------------------------- 1 file changed, 458 deletions(-) delete mode 100644 test/s_v130_to_v140_upgrade.js diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js deleted file mode 100644 index b1fe49cf8..000000000 --- a/test/s_v130_to_v140_upgrade.js +++ /dev/null @@ -1,458 +0,0 @@ -const Web3 = require("web3"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port -let BN = Web3.utils.BN; - -import latestTime from "./helpers/latestTime"; -import { duration } from "./helpers/utils"; -import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; -import { setUpPolymathNetwork, deployCappedSTOAndVerifyed, deployGPMAndVerifyed } from "./helpers/createInstances"; - -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 SecurityToken = artifacts.require("./SecurityToken.sol"); -const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); -const ManualApprovalTransferManagerFactory = artifacts.require("./ManualApprovalTransferManagerFactory.sol"); - -contract("Upgrade from v1.3.0 to v1.4.0", async (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 = new BN(web3.utils.toWei("250")); - const STOSetupCost = 0; - const address_zero = "0x0000000000000000000000000000000000000000"; - const one_address = "0x0000000000000000000000000000000000000001"; - - // 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_STRGetter; - - 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 STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; - // Prepare polymath network status - let currentTime; - - before(async () => { - currentTime = new BN(await latestTime()); - POLYMATH = accounts[0]; - ISSUER1 = accounts[1]; - ISSUER2 = accounts[2]; - ISSUER3 = accounts[3]; - MULTISIG = accounts[4]; - - I_DaiToken = await PolyTokenFaucet.new({ from: POLYMATH }); - - // ----------- POLYMATH NETWORK Configuration ------------ - - let instances = await setUpPolymathNetwork(POLYMATH, ISSUER1); - - [ - I_PolymathRegistry, - I_PolyToken, - I_FeatureRegistry, - I_ModuleRegistry, - I_ModuleRegistryProxy, - I_MRProxied, - I_GeneralTransferManagerFactory, - I_STFactory, - I_SecurityTokenRegistry, - I_SecurityTokenRegistryProxy, - I_STRProxied, - I_STRGetter - ] = instances; - - // STEP 4: Deploy the GeneralDelegateManagerFactory - [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(POLYMATH, I_MRProxied, 0); - - // STEP 5: Deploy the CappedSTOFactory - [I_CappedSTOFactory] = await deployCappedSTOAndVerifyed(POLYMATH, I_MRProxied, STOSetupCost); - - // 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[2].args._ticker, symbol1, "SecurityToken doesn't get deployed"); - I_SecurityToken1 = await SecurityToken.at(tx.logs[2].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[2].args._ticker, symbol2, "SecurityToken doesn't get deployed"); - I_SecurityToken2 = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - - // 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} - - 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: new BN(web3.utils.toWei("1")) }); - console.log(I_POLYOracle.address); - assert.notEqual(I_POLYOracle.address.valueOf(), address_zero, "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", address_zero, "ETH", { from: POLYMATH }); - assert.notEqual(I_USDOracle.address.valueOf(), address_zero, "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(STOSetupCost, new BN(0), new BN(0), I_USDTieredSTOProxyFactory.address, { - from: POLYMATH - }); - assert.notEqual(I_USDTieredSTOFactory.address.valueOf(), address_zero, "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(STOSetupCost, new BN(0), new BN(0), { from: POLYMATH }); - assert.notEqual(I_UpgradedCappedSTOFactory.address.valueOf(), address_zero, "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(0, new BN(0), new BN(0), { - from: POLYMATH - }); - assert.notEqual( - I_ManualApprovalTransferManagerFactory.address.valueOf(), - address_zero, - "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 = await latestTime() + duration.days(1); - let _endTime = _startTime + duration.days(180); - let _ratePerTier = [BN(0.1).mul(10 ** 18), BN(0.15).mul(10 ** 18), BN(0.2).mul(10 ** 18)]; - let _ratePerTierDiscountPoly = [BN(0), BN(0), BN(0)]; - let _tokensPerTierTotal = [BN(100).mul(10 ** 18), BN(200).mul(10 ** 18), BN(300).mul(10 ** 18)]; - let _tokensPerTierDiscountPoly = [BN(0), BN(0), BN(0)]; - let _nonAccreditedLimitUSD = new BN(100).mul(10 ** 18); - let _minimumInvestmentUSD = new BN(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, new BN(0), new BN(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 = await 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 = await SecurityToken.at(tx.logs[1].args._securityTokenAddress); - }); - */ - - // Launch NewCappedSTO for TOK2 - it("Should successfully launch CappedSTO for third security token", async () => { - let startTime = await latestTime() + duration.days(1); - let endTime = startTime + duration.days(30); - let cap = new BN(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, new BN(0), new BN(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, "0x0", new BN(0), new BN(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 = await ManualApprovalTransferManagerFactory.at(tx.logs[2].args._module); - }); - }); -}); From 91bac6f8e7232ba9b95b9693eeee4dc4b608cb4a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 5 Feb 2019 11:56:51 +0530 Subject: [PATCH 095/119] Moved result enum to interface --- contracts/interfaces/ITransferManager.sol | 9 +++------ contracts/interfaces/TransferManagerEnums.sol | 14 -------------- .../modules/TransferManager/TransferManager.sol | 2 +- contracts/tokens/SecurityToken.sol | 8 ++++---- 4 files changed, 8 insertions(+), 25 deletions(-) delete mode 100644 contracts/interfaces/TransferManagerEnums.sol diff --git a/contracts/interfaces/ITransferManager.sol b/contracts/interfaces/ITransferManager.sol index b248a98b3..1e7dd0f2c 100644 --- a/contracts/interfaces/ITransferManager.sol +++ b/contracts/interfaces/ITransferManager.sol @@ -1,16 +1,13 @@ pragma solidity ^0.5.0; -import "./TransferManagerEnums.sol"; - /** * @title Interface to be implemented by all Transfer Manager modules */ interface ITransferManager { + enum Result {INVALID, NA, VALID, FORCE_VALID} + /** * @notice Determines if the transfer between these two accounts can happen */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes calldata _data, bool _isTransfer) external returns( - TransferManagerEnums.Result - ); - + function verifyTransfer(address _from, address _to, uint256 _amount, bytes calldata _data, bool _isTransfer) external returns(Result); } diff --git a/contracts/interfaces/TransferManagerEnums.sol b/contracts/interfaces/TransferManagerEnums.sol deleted file mode 100644 index c097dddc7..000000000 --- a/contracts/interfaces/TransferManagerEnums.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity ^0.5.0; - -/** - * @title Container contract for transfer manager enums - */ -contract TransferManagerEnums { - //If verifyTransfer returns: - // FORCE_VALID, the transaction will always be valid, regardless of other TM results - // INVALID, then the transfer should not be allowed regardless of other TM results - // VALID, then the transfer is valid for this TM - // NA, then the result from this TM is ignored - enum Result {INVALID, NA, VALID, FORCE_VALID} - -} diff --git a/contracts/modules/TransferManager/TransferManager.sol b/contracts/modules/TransferManager/TransferManager.sol index dd93f5c25..f8b75c250 100644 --- a/contracts/modules/TransferManager/TransferManager.sol +++ b/contracts/modules/TransferManager/TransferManager.sol @@ -7,7 +7,7 @@ import "../../interfaces/ITransferManager.sol"; /** * @title Base abstract contract to be implemented by all Transfer Manager modules */ -contract TransferManager is ITransferManager, TransferManagerEnums, Module, Pausable { +contract TransferManager is ITransferManager, Module, Pausable { function unpause() public onlyOwner { super._unpause(); } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 7e7e14ba2..381209b7a 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -586,12 +586,12 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater module = modules[TRANSFER_KEY][i]; if (!modulesToData[module].isArchived) { unarchived = true; - TransferManagerEnums.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _data, _isTransfer); - if (valid == TransferManagerEnums.Result.INVALID) { + ITransferManager.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _data, _isTransfer); + if (valid == ITransferManager.Result.INVALID) { isInvalid = true; - } else if (valid == TransferManagerEnums.Result.VALID) { + } else if (valid == ITransferManager.Result.VALID) { isValid = true; - } else if (valid == TransferManagerEnums.Result.FORCE_VALID) { + } else if (valid == ITransferManager.Result.FORCE_VALID) { isForceValid = true; } } From 246f997f3b090cb6bdf6072d29bb8ccd436fe62b Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 5 Feb 2019 12:00:38 +0530 Subject: [PATCH 096/119] Removed references --- scripts/patch.js | 2 +- scripts/test.sh | 4 ++-- scripts/wintest.cmd | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/patch.js b/scripts/patch.js index bf006d160..602e0ef0b 100644 --- a/scripts/patch.js +++ b/scripts/patch.js @@ -14,7 +14,7 @@ fs.readFile(".solcover.js", "utf8", function(err, data) { let testCommand = "truffle test --network coverage"; fs.readdirSync("./test").forEach(file => { - if (file != "a_poly_oracle.js" && file != "s_v130_to_v140_upgrade.js") testCommand = testCommand + " test\\\\" + file; + if (file != "a_poly_oracle.js") testCommand = testCommand + " test\\\\" + file; }); testCommand = testCommand + "',"; let result = data.replace(regex2, testCommand); diff --git a/scripts/test.sh b/scripts/test.sh index 039cb43bb..538810761 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -105,9 +105,9 @@ else 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` + node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.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` + node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js` fi fi diff --git a/scripts/wintest.cmd b/scripts/wintest.cmd index e5a2a6a61..26976da18 100644 --- a/scripts/wintest.cmd +++ b/scripts/wintest.cmd @@ -18,7 +18,5 @@ for %%i in (test\*.js) do call :PushTest %%i :PushTest if NOT "%1" == "test\a_poly_oracle.js" ( - if NOT "%1" == "test\s_v130_to_v140_upgrade.js" ( - set var=%var% %1 - ) + set var=%var% %1 ) From a577287b24fff9b9e0c8a21c5f753674d442baf2 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 5 Feb 2019 18:04:36 +0530 Subject: [PATCH 097/119] add isAccredited in the modifyWhitelist --- contracts/libraries/VersionUtils.sol | 17 +- contracts/modules/Module.sol | 5 - contracts/modules/STO/DummySTO.sol | 2 +- contracts/modules/STO/DummySTOFactory.sol | 12 +- .../GeneralTransferManager.sol | 186 ++- .../storage/GeneralTransferManagerStorage.sol | 98 +- contracts/tokens/SecurityToken.sol | 9 - test/h_general_transfer_manager.js | 1204 +++++++++-------- test/helpers/signData.js | 4 +- 9 files changed, 751 insertions(+), 786 deletions(-) diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 22c87b2dd..88ca792ed 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -110,20 +110,21 @@ library VersionUtils { /** * @notice Used to packed the KYC data */ - function packKYC(uint64 _a, uint64 _b, uint64 _c, uint8 _d, uint8 _e) internal pure returns(uint256) { - return (uint256(_a) << 192) | (uint256(_b) << 128) | (uint256(_c) << 64) | (uint256(_d) << 16) | uint256(_e); + function packKYC(uint64 _a, uint64 _b, uint64 _c, uint8 _d, uint8 _e, uint8 _f) internal pure returns(uint256) { + return (uint256(_a) << 184) | (uint256(_b) << 120) | (uint256(_c) << 56) | (uint256(_d) << 24) | (uint256(_e) << 16) | uint256(_f); } /** * @notice Used to convert packed data into KYC data * @param _packedVersion Packed data */ - function unpackKYC(uint256 _packedVersion) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added) { - fromTime = uint64(_packedVersion >> 192); - toTime = uint64(_packedVersion >> 128); - expiryTime = uint64(_packedVersion >> 64); - canBuy = uint8(_packedVersion >> 16); - added = uint8(_packedVersion); + function unpackKYC(uint256 _packedVersion) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added, uint8 accredited) { + fromTime = uint64(_packedVersion >> 184); + toTime = uint64(_packedVersion >> 120); + expiryTime = uint64(_packedVersion >> 56); + canBuy = uint8(_packedVersion >> 24); + added = uint8(_packedVersion >> 16); + accredited = uint8(_packedVersion); } } diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index bcce7781c..4ed977d54 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -53,11 +53,6 @@ contract Module is IModule, ModuleStorage { _; } - modifier onlyST() { - require(msg.sender == securityToken, "Unathorized"); - _; - } - /** * @notice used to withdraw the fee by the factory owner */ diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 502e88ba4..8b1a9101d 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -25,7 +25,7 @@ contract DummySTO is DummySTOStorage, STO { * @param _cap Maximum No. of tokens for sale * @param _someString Any string that contails the details */ - function configure(uint256 _startTime, uint256 _endTime, uint256 _cap, string memory _someString) public onlyST { + function configure(uint256 _startTime, uint256 _endTime, uint256 _cap, string memory _someString) public onlyFactory { startTime = _startTime; endTime = _endTime; cap = _cap; diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index 7e5ab11d2..ee84a4251 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -46,12 +46,12 @@ contract DummySTOFactory is ModuleFactory { address polyToken = _takeFee(); //Check valid bytes - can only call module init function address dummySTO = address(new DummySTOProxy(msg.sender, polyToken, logicContract)); - // //Checks that _data is valid (not calling anything it shouldn't) - // require(Util.getSig(_data) == IBoot(dummySTO).getInitFunction(), "Invalid data"); - // bool success; - // /*solium-disable-next-line security/no-low-level-calls*/ - // (success, ) = dummySTO.call(_data); - // require(success, "Unsuccessfull call"); + //Checks that _data is valid (not calling anything it shouldn't) + require(Util.getSig(_data) == IBoot(dummySTO).getInitFunction(), "Invalid data"); + bool success; + /*solium-disable-next-line security/no-low-level-calls*/ + (success, ) = dummySTO.call(_data); + require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ emit GenerateModuleFromFactory(dummySTO, getName(), address(this), msg.sender, setupCost, now); return dummySTO; diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 1da18cf30..6b2f56651 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -27,7 +27,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage // 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(uint256 _defaultFromTime, uint256 _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 @@ -41,7 +41,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, - bool _canBuyFromSTO + bool _canBuyFromSTO, + bool _isAccredited ); /** @@ -62,21 +63,14 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return bytes4(0); } - /** - * @notice This function use to initialize the local variables of the contract - */ - function initialize() public onlyST { - IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTISSUANCES, true); - } - /** * @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(uint256 _defaultFromTime, uint256 _defaultToTime) public withPerm(FLAGS) { - IDataStore(getDataStore()).setUint256(Encoder.getKey("fromTime", DEFAULTS), _defaultFromTime); - IDataStore(getDataStore()).setUint256(Encoder.getKey("toTime", DEFAULTS), _defaultFromTime); + function changeDefaults(uint64 _defaultFromTime, uint64 _defaultToTime) public withPerm(FLAGS) { + defaults.fromTime = _defaultFromTime; + defaults.toTime = _defaultToTime; emit ChangeDefaults(_defaultFromTime, _defaultToTime); } @@ -85,7 +79,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _issuanceAddress new address for the issuance */ function changeIssuanceAddress(address _issuanceAddress) public withPerm(FLAGS) { - IDataStore(getDataStore()).setAddress(ISSUANCE_ADD, _issuanceAddress); + issuanceAddress = _issuanceAddress; emit ChangeIssuanceAddress(_issuanceAddress); } @@ -94,7 +88,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _signingAddress new address for the signing */ function changeSigningAddress(address _signingAddress) public withPerm(FLAGS) { - IDataStore(getDataStore()).setAddress(SIGNING_ADD, _signingAddress); + signingAddress = _signingAddress; emit ChangeSigningAddress(_signingAddress); } @@ -105,7 +99,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllTransfers flag value */ function changeAllowAllTransfers(bool _allowAllTransfers) public withPerm(FLAGS) { - IDataStore(getDataStore()).setBool(ALLOWALLTRANSFERS, _allowAllTransfers); + allowAllTransfers = _allowAllTransfers; emit AllowAllTransfers(_allowAllTransfers); } @@ -116,7 +110,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllWhitelistTransfers flag value */ function changeAllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers) public withPerm(FLAGS) { - IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTTRANSFERS, _allowAllWhitelistTransfers); + allowAllWhitelistTransfers = _allowAllWhitelistTransfers; emit AllowAllWhitelistTransfers(_allowAllWhitelistTransfers); } @@ -127,7 +121,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllWhitelistIssuances flag value */ function changeAllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances) public withPerm(FLAGS) { - IDataStore(getDataStore()).setBool(ALLOWALLWHITELISTISSUANCES, _allowAllWhitelistIssuances); + allowAllWhitelistIssuances = _allowAllWhitelistIssuances; emit AllowAllWhitelistIssuances(_allowAllWhitelistIssuances); } @@ -138,7 +132,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _allowAllBurnTransfers flag value */ function changeAllowAllBurnTransfers(bool _allowAllBurnTransfers) public withPerm(FLAGS) { - IDataStore(getDataStore()).setBool(ALLOWALLBURNTRANSFERS, _allowAllBurnTransfers); + allowAllBurnTransfers = _allowAllBurnTransfers; emit AllowAllBurnTransfers(_allowAllBurnTransfers); } @@ -165,30 +159,29 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint64 toExpiry; uint64 toTime; uint8 canBuyFromSTO; - IDataStore dataStore = IDataStore(getDataStore()); - if (dataStore.getBool(ALLOWALLTRANSFERS)) { + if (allowAllTransfers) { //All transfers allowed, regardless of whitelist return Result.VALID; } - if (dataStore.getBool(ALLOWALLBURNTRANSFERS) && (_to == address(0))) { + if (allowAllBurnTransfers && (_to == address(0))) { return Result.VALID; } (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValuesToUser(_from, _to); - if (dataStore.getBool(ALLOWALLWHITELISTTRANSFERS)) { + if (allowAllWhitelistTransfers) { //Anyone on the whitelist can transfer, regardless of time return (_onWhitelist(toExpiry) && _onWhitelist(fromExpiry)) ? Result.VALID : Result.NA; } // Using the local variables to avoid the stack too deep error (fromTime, toTime) = _adjustTimes(fromTime, toTime); - if (_from == dataStore.getAddress(ISSUANCE_ADD)) { + if (_from == issuanceAddress) { // Possible STO transaction, but investor not allowed to purchased from STO - if ((canBuyFromSTO == 0) && _isSTOAttached()) { + if ((canBuyFromSTO == uint8(0)) && _isSTOAttached()) { return Result.NA; } // if allowAllWhitelistIssuances is true, so time stamp ignored - if (dataStore.getBool(ALLOWALLWHITELISTISSUANCES)) { + if (allowAllWhitelistIssuances) { return _onWhitelist(toExpiry) ? Result.VALID : Result.NA; } else { return (_onWhitelist(toExpiry) && (toTime <= uint64(now))) ? Result.VALID : Result.NA; @@ -210,18 +203,20 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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. + * @param _isAccredited is used to differentiate whether the investor is Accredited or not. */ function modifyWhitelist( address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, - bool _canBuyFromSTO + bool _canBuyFromSTO, + bool _isAccredited ) public withPerm(WHITELIST) { - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); } /** @@ -231,22 +226,23 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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. + * @param _isAccredited is used to differentiate whether the investor is Accredited or not. */ - function _modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO) internal { + function _modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO, bool _isAccredited) internal { require(_investor != address(0), "Invalid investor"); uint8 added; - uint8 canBuyFromSTO = 0; + uint8 canBuyFromSTO; + uint8 accredited; IDataStore dataStore = IDataStore(getDataStore()); - (,,,,added) = _getValues(_investor); + (,,,,added,) = _getValues(_investor, dataStore); if (added == uint8(0)) { - dataStore.insertAddress(INVESTORS_ARRAY, _investor); + investors.push(_investor); } - if (_canBuyFromSTO) { - canBuyFromSTO = 1; - } - uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1)); + canBuyFromSTO = _canBuyFromSTO ? 1 : 0; + accredited = _isAccredited ? 1 : 0; + uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1), accredited); dataStore.setUint256(_getKey(WHITELIST, _investor), _data); - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); } /** @@ -255,21 +251,30 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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 _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 + * @param _canBuyFromSTO An array of boolean values. + * @param _isAccredited An array of boolean values to differentiate whether the investor is Accredited or not. */ function modifyWhitelistMulti( address[] memory _investors, uint256[] memory _fromTimes, uint256[] memory _toTimes, uint256[] memory _expiryTimes, - bool[] memory _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"); + bool[] memory _canBuyFromSTO, + bool[] memory _isAccredited + ) + public + withPerm(WHITELIST) + { + require( + _investors.length == _fromTimes.length && + _fromTimes.length == _toTimes.length && + _toTimes.length == _expiryTimes.length && + _canBuyFromSTO.length == _toTimes.length && + _canBuyFromSTO.length == _isAccredited.length, + "Mismatched input lengths" + ); 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], _isAccredited[i]); } } @@ -280,6 +285,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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. + * @param _isAccredited is used to differentiate whether the investor is Accredited 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) @@ -291,6 +297,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO, + bool _isAccredited, uint256 _validFrom, uint256 _validTo, uint256 _nonce, @@ -302,15 +309,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(_validFrom <= now, "ValidFrom is too early"); /*solium-disable-next-line security/no-block-members*/ require(_validTo >= now, "ValidTo is too late"); - bytes32 _key = keccak256(abi.encodePacked("nonceMap", _investor, _nonce)); - require(!IDataStore(getDataStore()).getBool(_key), "Already used signature"); - //nonceMap[_investor][_nonce] = true; - IDataStore(getDataStore()).setBool(_key, true); + 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, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited, _validFrom, _validTo, _nonce) ); _checkSig(hash, _signature); - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); } /** @@ -320,7 +325,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage //Check that the signature is valid //sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address address signer = _hash.toEthSignedMessageHash().recover(_signature); - require(signer == Ownable(securityToken).owner() || signer == IDataStore(getDataStore()).getAddress(SIGNING_ADD), "Incorrect signer"); + require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer"); } /** @@ -347,10 +352,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint64 adjustedFromTime = _fromTime; uint64 adjustedToTime = _toTime; if (_fromTime == 0) { - adjustedFromTime = uint64(IDataStore(getDataStore()).getUint256(Encoder.getKey("fromTime", DEFAULTS))); + adjustedFromTime = defaults.fromTime; } if (_toTime == 0) { - adjustedToTime = uint64(IDataStore(getDataStore()).getUint256(Encoder.getKey("toTime", DEFAULTS))); + adjustedToTime = defaults.toTime; } return (adjustedFromTime, adjustedToTime); } @@ -359,22 +364,30 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function _getValues(address _investor) internal view returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuyFromSTO, uint8 added) { - IDataStore dataStore = IDataStore(getDataStore()); + function _getValues(address _investor, IDataStore dataStore) internal view returns( + uint64 fromTime, + uint64 toTime, + uint64 expiryTime, + uint8 canBuyFromSTO, + uint8 added, + uint8 isAccredited + ) + { uint256 _whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); - (fromTime, toTime, expiryTime, canBuyFromSTO, added) = VersionUtils.unpackKYC(_whitelistData); + (fromTime, toTime, expiryTime, canBuyFromSTO, added, isAccredited) = VersionUtils.unpackKYC(_whitelistData); } - function _getValuesToUser(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry ) { - (fromTime,, fromExpiry, canBuyFromSTO,) = _getValues(_from); - (, toTime, toExpiry,,) = _getValues(_to); + function _getValuesToUser(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry) { + IDataStore dataStore = IDataStore(getDataStore()); + (fromTime,, fromExpiry,,,) = _getValues(_from, dataStore); + (, toTime, toExpiry, canBuyFromSTO,,) = _getValues(_to, dataStore); } /** * @dev Returns list of all investors */ function getInvestors() public view returns(address[] memory) { - return IDataStore(getDataStore()).getAddressArray(INVESTORS_ARRAY); + return investors; } /** @@ -385,10 +398,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256[] memory fromTimes, uint256[] memory toTimes, uint256[] memory expiryTimes, - bool[] memory canBuyFromSTOs + bool[] memory canBuyFromSTOs, + bool[] memory isAccrediteds ) { - (fromTimes, toTimes, expiryTimes, canBuyFromSTOs) = _investorsData(getInvestors()); - return (getInvestors(), fromTimes, toTimes, expiryTimes, canBuyFromSTOs); + (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _investorsData(getInvestors()); + return (getInvestors(), fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); } @@ -399,6 +413,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256[] memory, uint256[] memory, uint256[] memory, + bool[] memory, bool[] memory ) { return _investorsData(_investors); @@ -408,53 +423,22 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256[] memory, uint256[] memory, uint256[] memory, + bool[] memory, bool[] memory ) { 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); + bool[] memory isAccrediteds = new bool[](_investors.length); for (uint256 i = 0; i < _investors.length; i++) { uint8 canBuyFromSTO; - (fromTimes[i], toTimes[i], expiryTimes[i], canBuyFromSTO,) = _getValues(_investors[i]); - if (canBuyFromSTO == 0) { - canBuyFromSTOs[i] = false; - } else { - canBuyFromSTOs[i] = true; - } + uint8 isAccredited; + (fromTimes[i], toTimes[i], expiryTimes[i], canBuyFromSTO,,isAccredited) = _getValues(_investors[i], IDataStore(getDataStore())); + canBuyFromSTOs[i] = canBuyFromSTO == 0 ? false : true; + isAccrediteds[i] = isAccredited == 0 ? false : true; } - return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs); - } - - function getSigningAddress() external view returns(address) { - return IDataStore(getDataStore()).getAddress(SIGNING_ADD); - } - - function getIssuanceAddress() external view returns(address) { - return IDataStore(getDataStore()).getAddress(ISSUANCE_ADD); - } - - function allowAllTransfers() external view returns(bool) { - return IDataStore(getDataStore()).getBool(ALLOWALLTRANSFERS); - } - - function allowAllWhitelistTransfers() external view returns(bool) { - return IDataStore(getDataStore()).getBool(ALLOWALLWHITELISTTRANSFERS); - } - - function allowAllWhitelistIssuances() external view returns(bool) { - return IDataStore(getDataStore()).getBool(ALLOWALLWHITELISTISSUANCES); - } - - function allowAllBurnTransfers() external view returns(bool) { - return IDataStore(getDataStore()).getBool(ALLOWALLBURNTRANSFERS); - } - - function getDefaultTimes() external view returns(uint256, uint256) { - return( - IDataStore(getDataStore()).getUint256(Encoder.getKey("fromTime", DEFAULTS)), - IDataStore(getDataStore()).getUint256(Encoder.getKey("toTime", DEFAULTS)) - ); + return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); } /** diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index 6e804062b..b481e31d5 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -5,59 +5,51 @@ pragma solidity ^0.5.0; */ contract GeneralTransferManagerStorage { - bytes32 public constant INVESTORS_ARRAY = "INVESTORS_ARRAY"; - bytes32 public constant SIGNING_ADD = "SIGNING_ADDRESS"; - bytes32 public constant ISSUANCE_ADD = "ISSUANCE_ADDRESS"; bytes32 public constant WHITELIST = "WHITELIST"; bytes32 public constant FLAGS = "FLAGS"; - bytes32 public constant ALLOWALLTRANSFERS = "ALLOW_ALL_TRANFERS"; - bytes32 public constant ALLOWALLWHITELISTTRANSFERS = "ALLOW_ALL_WHITELIST_TRANSFERS"; - bytes32 public constant ALLOWALLWHITELISTISSUANCES = "ALLOW_ALL_WHITELIST_ISSUANCES"; - bytes32 public constant ALLOWALLBURNTRANSFERS = "ALLOW_ALL_BURN_TRANSFERS"; - bytes32 public constant DEFAULTS = "DEFAULTS"; - - // Data Structure of GTM - /** - //Address from which issuances come - address public issuanceAddress = address(0); - - //Address which can sign whitelist changes - address public signingAddress = address(0); - - //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; - */ + + //Address from which issuances come + address public issuanceAddress = address(0); + + //Address which can sign whitelist changes + address public signingAddress = address(0); + +/* + //from and to timestamps that an investor can send / receive tokens respectively + struct TimeRestriction { + uint64 fromTime; + uint64 toTime; + uint64 expiryTime; + uint8 canBuyFromSTO; + uint8 added; + } + + // An address can only send / receive tokens once their corresponding uint256 > block.number + // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) + mapping (address => TimeRestriction) public whitelist; +*/ + // 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; + + // 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/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 8e3115589..12bcd91a1 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -264,15 +264,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater _label ); names[moduleName].push(module); - if (Util.getSig(_data) == "") { - IBoot(module).initialize(); - } else { - require(Util.getSig(_data) == IBoot(module).getInitFunction(), "Provided data is not valid"); - bool success; - /*solium-disable-next-line security/no-low-level-calls*/ - (success, ) = module.call(_data); - require(success, "Unsuccessful call"); - } //Emit log event /*solium-disable-next-line security/no-block-members*/ emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label, now); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index f32240ca5..bbb3d4c66 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -1,7 +1,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; -import { getSignGTMData, signData } from "./helpers/signData"; +import { getSignGTMData } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; @@ -209,6 +209,7 @@ contract("GeneralTransferManager", async (accounts) => { currentTime + currentTime.add(new BN(duration.days(90))), currentTime + currentTime.add(new BN(duration.days(965))), false, + false, { from: account_issuer } @@ -227,6 +228,7 @@ contract("GeneralTransferManager", async (accounts) => { [toTime1, toTime2], [expiryTime1, expiryTime2], [false, false], + [false, false], { from: account_issuer, gas: 6000000 @@ -249,17 +251,17 @@ contract("GeneralTransferManager", async (accounts) => { it("Should whitelist lots of addresses and check gas", async () => { let mockInvestors = []; - for (let i = 0; i < 90; i++) { + for (let i = 0; i < 100; i++) { mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0, 42 - i.toString().length) + i.toString()); } - let times = range1(90); - let bools = rangeB(90); - let tx = await I_GeneralTransferManager.modifyWhitelistMulti(mockInvestors, times, times, times, bools, { + let times = range1(100); + let bools = rangeB(100); + let tx = await I_GeneralTransferManager.modifyWhitelistMulti(mockInvestors, times, times, times, bools, bools, { from: account_issuer, gas: 7900000 }); - console.log("Multi Whitelist x 90: " + tx.receipt.gasUsed); + console.log("Multi Whitelist x 100: " + tx.receipt.gasUsed); assert.deepEqual( await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors) @@ -267,6 +269,11 @@ contract("GeneralTransferManager", async (accounts) => { }); it("Should mint the tokens to the affiliates", async () => { + console.log(` + Estimate gas cost for minting the tokens: ${await I_SecurityToken.mintMulti.estimateGas([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { + from: account_issuer + })} + `) await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { from: account_issuer, gas: 6000000 @@ -343,33 +350,6 @@ contract("GeneralTransferManager", async (accounts) => { }); }); - describe("Verify the values of the public variables", async() => { - - it("Should the signing address be 0x", async() => { - assert.equal(await I_GeneralTransferManager.getSigningAddress.call(), address_zero); - }); - - it("Should issuance address will be 0x", async() => { - assert.equal(await I_GeneralTransferManager.getIssuanceAddress.call(), address_zero); - }); - - it("Should allowAllTransfers be false", async() => { - assert.isFalse(await I_GeneralTransferManager.allowAllTransfers.call()); - }); - - it("Should allowAllWhitelistTransfers be false", async() => { - assert.isFalse(await I_GeneralTransferManager.allowAllWhitelistTransfers.call()); - }); - - it("Should allowAllWhitelistIssuances be true", async() => { - assert.isTrue(await I_GeneralTransferManager.allowAllWhitelistIssuances.call()); - }); - - it("Should allowAllBurnTransfers be false", async() => { - assert.isFalse(await I_GeneralTransferManager.allowAllBurnTransfers.call()); - }); - }) - describe("Buy tokens using on-chain whitelist", async () => { it("Should buy the tokens -- Failed due to investor is not in the whitelist", async () => { await catchRevert(I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); @@ -384,6 +364,7 @@ contract("GeneralTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 @@ -400,6 +381,9 @@ contract("GeneralTransferManager", async (accounts) => { await increaseTime(5000); // Mint some tokens + console.log( + `Gas usage of minting of tokens: ${await I_DummySTO.generateTokens.estimateGas(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })}` + ) await I_DummySTO.generateTokens(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); @@ -432,574 +416,592 @@ contract("GeneralTransferManager", async (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, new BN(0), new BN(0), currentTime.add(new BN(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, - // currentTime, - // currentTime, - // currentTime.add(new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - // assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - // }); - - // it("Add a from default and check transfers are disabled then enabled in the future", async () => { - // let tx = await I_GeneralTransferManager.changeDefaults(currentTime.add(new BN(duration.days(12))), new BN(0), { from: token_owner }); - // await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); - // await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); - // await increaseTime(duration.days(5)); - // await I_SecurityToken.transfer(account_investor2, new BN(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, currentTime.add(new BN(duration.days(16))), { from: token_owner }); - // await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); - // await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); - // await increaseTime(duration.days(2)); - // await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); - // // revert changes - // await I_GeneralTransferManager.modifyWhitelist(account_investor2, new BN(0), new BN(0), new BN(0), false, { - // from: account_issuer, - // gas: 6000000 - // }); - // await I_GeneralTransferManager.changeDefaults(0, new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // }); - - // it("Should provide the permission and change the signing address", async () => { - // let log = await I_GeneralPermissionManager.addDelegate(account_delegate, web3.utils.fromAscii("My details"), { from: token_owner }); - // assert.equal(log.logs[0].args._delegate, account_delegate); - - // await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { - // from: token_owner - // }); - - // assert.isTrue( - // await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS")) - // ); - // console.log(JSON.stringify(signer)); - // let tx = await I_GeneralTransferManager.changeSigningAddress(signer.address, { from: account_delegate }); - // assert.equal(tx.logs[0].args._signingAddress, signer.address); - // }); - - // 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 = await latestTime(); - // let validTo = await latestTime() + duration.days(5); - // let nonce = 5; - // const sig = getSignGTMData( - // account_investor2, - // account_investor2, - // fromTime, - // toTime, - // expiryTime, - // true, - // validFrom, - // validTo, - // nonce, - // signer.privateKey - // ); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistSigned( - // account_investor2, - // fromTime, - // toTime, - // expiryTime, - // true, - // validFrom, - // validTo, - // nonce, - // sig, - // { - // from: account_investor2, - // gas: 6000000 - // } - // ) - // ); - // }); - - // 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 = await latestTime() - 100; - // let validTo = await latestTime() - 1; - // let nonce = 5; - // const sig = getSignGTMData( - // I_GeneralTransferManager.address, - // account_investor2, - // fromTime, - // toTime, - // expiryTime, - // true, - // validFrom, - // validTo, - // nonce, - // signer.privateKey - // ); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistSigned( - // account_investor2, - // fromTime, - // toTime, - // expiryTime, - // true, - // validFrom, - // validTo, - // nonce, - // sig, - // { - // from: account_investor2, - // gas: 6000000 - // } - // ) - // ); - // }); - - // 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 = await latestTime(); - // let validTo = await latestTime() + 60 * 60; - // let nonce = 5; - // const sig = getSignGTMData( - // account_investor2, - // account_investor2, - // fromTime, - // toTime, - // expiryTime, - // true, - // validFrom, - // validTo, - // nonce, - // "2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200" - // ); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistSigned( - // account_investor2, - // fromTime, - // toTime, - // expiryTime, - // true, - // validFrom, - // validTo, - // nonce, - // sig, - // { - // from: account_investor2, - // gas: 6000000 - // } - // ) - // ); - // }); - - // it("Should Buy the tokens with signers signature", async () => { - // // Add the Investor in to the whitelist - // //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - // let validFrom = await latestTime(); - // let validTo = await latestTime() + duration.days(5); - // let nonce = 5; - // const sig = getSignGTMData( - // I_GeneralTransferManager.address, - // account_investor2, - // currentTime.toNumber(), - // currentTime.add(new BN(duration.days(100))).toNumber(), - // expiryTime + duration.days(200), - // true, - // validFrom, - // validTo, - // nonce, - // signer.privateKey - // ); - - // let tx = await I_GeneralTransferManager.modifyWhitelistSigned( - // account_investor2, - // currentTime.toNumber(), - // currentTime.add(new BN(duration.days(100))).toNumber(), - // expiryTime + duration.days(200), - // true, - // validFrom, - // validTo, - // nonce, - // sig, - // { - // 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - - // assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - // }); - - // 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 = await latestTime(); - // let validTo = await latestTime() + duration.days(5); - // let nonce = 5; - // const sig = getSignGTMData( - // I_GeneralTransferManager.address, - // account_investor2, - // currentTime.toNumber(), - // currentTime.add(new BN(duration.days(100))).toNumber(), - // expiryTime + duration.days(200), - // true, - // validFrom, - // validTo, - // nonce, - // signer.privateKey - // ); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistSigned( - // account_investor2, - // currentTime.toNumber(), - // currentTime.add(new BN(duration.days(100))).toNumber(), - // expiryTime + duration.days(200), - // true, - // validFrom, - // validTo, - // nonce, - // sig, - // { - // from: account_investor2, - // gas: 6000000 - // } - // ) - // ); - // }); - - // it("Should sign with token owner key", async () => { - // // Add the Investor in to the whitelist - // //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk - // let validFrom = await latestTime(); - // let validTo = await latestTime() + duration.days(5); - // let nonce = 6; - // const sig = getSignGTMData( - // I_GeneralTransferManager.address, - // account_investor2, - // currentTime.toNumber(), - // currentTime.add(new BN(duration.days(100))).toNumber(), - // expiryTime + duration.days(200), - // true, - // validFrom, - // validTo, - // nonce, - // "0x" + token_owner_pk - // ); - - // await I_GeneralTransferManager.modifyWhitelistSigned( - // account_investor2, - // currentTime.toNumber(), - // currentTime.add(new BN(duration.days(100))).toNumber(), - // expiryTime + duration.days(200), - // true, - // validFrom, - // validTo, - // nonce, - // sig, - // { - // from: account_investor2, - // gas: 6000000 - // } - // ) - - // }); - - // it("Should fail in changing the signing address", async () => { - // await catchRevert(I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_investor4 })); - // }); - - // 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 fail to pull fees as no budget set", async () => { - // await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_polymath })); - // }); - - // it("Should set a budget for the GeneralTransferManager", async () => { - // await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, new BN(10).pow(new BN(19)), true, { from: token_owner }); - - // await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); - // await I_PolyToken.getTokens(new BN(10).pow(new BN(19)), token_owner); - // await I_PolyToken.transfer(I_SecurityToken.address, new BN(10).pow(new BN(19)), { from: token_owner }); - // }); - - // it("Factory owner should pull fees - fails as not permissioned by issuer", async () => { - // await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate })); - // }); - - // it("Factory owner should pull fees", async () => { - // await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FEE_ADMIN"), true, { - // from: token_owner - // }); - // let balanceBefore = await I_PolyToken.balanceOf(account_polymath); - // await I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate }); - // let balanceAfter = await I_PolyToken.balanceOf(account_polymath); - // assert.equal(balanceBefore.add(new BN(web3.utils.toWei("1", "ether"))).toString(), balanceAfter.toString(), "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 }); - // await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); - // }); - - // 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 = await latestTime(); - // let toTime = await latestTime() + duration.days(20); - // let expiryTime = toTime + duration.days(10); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistMulti( - // [account_investor3, account_investor4], - // [fromTime, fromTime], - // [toTime, toTime], - // [expiryTime, expiryTime], - // [true, true], - // { - // from: account_delegate, - // gas: 6000000 - // } - // ) - // ); - // }); - - // it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - // let fromTime = await latestTime(); - // let toTime = await latestTime() + duration.days(20); - // let expiryTime = toTime + duration.days(10); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistMulti( - // [account_investor3, account_investor4], - // [fromTime], - // [toTime, toTime], - // [expiryTime, expiryTime], - // [1, 1], - // { - // from: account_delegate, - // gas: 6000000 - // } - // ) - // ); - // }); - - // it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - // let fromTime = await latestTime(); - // let toTime = await latestTime() + duration.days(20); - // let expiryTime = toTime + duration.days(10); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistMulti( - // [account_investor3, account_investor4], - // [fromTime, fromTime], - // [toTime], - // [expiryTime, expiryTime], - // [true, true], - // { - // from: account_delegate, - // gas: 6000000 - // } - // ) - // ); - // }); - - // it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { - // let fromTime = await latestTime(); - // let toTime = await latestTime() + duration.days(20); - // let expiryTime = toTime + duration.days(10); - - // await catchRevert( - // I_GeneralTransferManager.modifyWhitelistMulti( - // [account_investor3, account_investor4], - // [fromTime, fromTime], - // [toTime, toTime], - // [expiryTime], - // [true, true], - // { - // from: account_delegate, - // gas: 6000000 - // } - // ) - // ); - // }); - - // it("Should successfully add the investors in whitelist", async () => { - // let fromTime = await latestTime(); - // let toTime = await latestTime() + duration.days(20); - // let expiryTime = toTime + duration.days(10); - - // 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.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, ""), - // "GeneralTransferManager", - // "Wrong Module added" - // ); - // assert.equal( - // await I_GeneralTransferManagerFactory.description.call(), - // "Manage transfers using a time based whitelist", - // "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.", - // "Wrong Module added" - // ); - // assert.equal(await I_GeneralTransferManagerFactory.version.call(), "2.1.0"); - // }); - - // 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.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.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"); - // }); - - // 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"); - // }); - - // it("Should get the version of factory", async () => { - // let version = await I_DummySTOFactory.version.call(); - // assert.equal(version, "1.0.0"); - // }); - // }); - - // 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)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); - // }); - - // it("Should get the raised amount of poly", async () => { - // assert.equal((await I_DummySTO.getRaised.call(1)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); - // }); - - // it("Should get the investors", async () => { - // assert.equal((await I_DummySTO.getNumberInvestors.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"); - // }); - - // it("Should get the amount of tokens sold", async () => { - // assert.equal(await I_DummySTO.getTokensSold.call(), 0); - // }); - // }); + 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, new BN(0), new BN(0), currentTime.add(new BN(duration.days(20))), true, false, { + 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, + currentTime, + currentTime, + currentTime.add(new BN(duration.days(20))), + true, + 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, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + }); + + it("Add a from default and check transfers are disabled then enabled in the future", async () => { + let tx = await I_GeneralTransferManager.changeDefaults(currentTime.add(new BN(duration.days(12))), new BN(0), { from: token_owner }); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 }); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 })); + await increaseTime(duration.days(5)); + await I_SecurityToken.transfer(account_investor2, new BN(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, currentTime.add(new BN(duration.days(16))), { from: token_owner }); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: account_investor2 })); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: account_investor1 }); + await increaseTime(duration.days(2)); + await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); + // revert changes + await I_GeneralTransferManager.modifyWhitelist(account_investor2, new BN(0), new BN(0), new BN(0), false, false, { + from: account_issuer, + gas: 6000000 + }); + await I_GeneralTransferManager.changeDefaults(0, new BN(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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + }); + + it("Should provide the permission and change the signing address", async () => { + let log = await I_GeneralPermissionManager.addDelegate(account_delegate, web3.utils.fromAscii("My details"), { from: token_owner }); + assert.equal(log.logs[0].args._delegate, account_delegate); + + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS"), true, { + from: token_owner + }); + + assert.isTrue( + await I_GeneralPermissionManager.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FLAGS")) + ); + console.log(JSON.stringify(signer)); + let tx = await I_GeneralTransferManager.changeSigningAddress(signer.address, { from: account_delegate }); + assert.equal(tx.logs[0].args._signingAddress, signer.address); + }); + + 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 = await latestTime(); + let validTo = await latestTime() + duration.days(5); + let nonce = 5; + const sig = getSignGTMData( + account_investor2, + account_investor2, + fromTime, + toTime, + expiryTime, + true, + false, + validFrom, + validTo, + nonce, + signer.privateKey + ); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + false, + validFrom, + validTo, + nonce, + sig, + { + from: account_investor2, + gas: 6000000 + } + ) + ); + }); + + 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 = await latestTime() - 100; + let validTo = await latestTime() - 1; + let nonce = 5; + const sig = getSignGTMData( + I_GeneralTransferManager.address, + account_investor2, + fromTime, + toTime, + expiryTime, + true, + false, + validFrom, + validTo, + nonce, + signer.privateKey + ); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + false, + validFrom, + validTo, + nonce, + sig, + { + from: account_investor2, + gas: 6000000 + } + ) + ); + }); + + 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 = await latestTime(); + let validTo = await latestTime() + 60 * 60; + let nonce = 5; + const sig = getSignGTMData( + account_investor2, + account_investor2, + fromTime, + toTime, + expiryTime, + true, + false, + validFrom, + validTo, + nonce, + "2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200" + ); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + fromTime, + toTime, + expiryTime, + true, + false, + validFrom, + validTo, + nonce, + sig, + { + from: account_investor2, + gas: 6000000 + } + ) + ); + }); + + it("Should Buy the tokens with signers signature", async () => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = await latestTime(); + let validTo = await latestTime() + duration.days(5); + let nonce = 5; + const sig = getSignGTMData( + I_GeneralTransferManager.address, + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + false, + validFrom, + validTo, + nonce, + signer.privateKey + ); + + let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + false, + validFrom, + validTo, + nonce, + sig, + { + 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + }); + + 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 = await latestTime(); + let validTo = await latestTime() + duration.days(5); + let nonce = 5; + const sig = getSignGTMData( + I_GeneralTransferManager.address, + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + false, + validFrom, + validTo, + nonce, + signer.privateKey + ); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + false, + validFrom, + validTo, + nonce, + sig, + { + from: account_investor2, + gas: 6000000 + } + ) + ); + }); + + it("Should sign with token owner key", async () => { + // Add the Investor in to the whitelist + //tmAddress, investorAddress, fromTime, toTime, validFrom, validTo, pk + let validFrom = await latestTime(); + let validTo = await latestTime() + duration.days(5); + let nonce = 6; + const sig = getSignGTMData( + I_GeneralTransferManager.address, + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + false, + validFrom, + validTo, + nonce, + "0x" + token_owner_pk + ); + + await I_GeneralTransferManager.modifyWhitelistSigned( + account_investor2, + currentTime.toNumber(), + currentTime.add(new BN(duration.days(100))).toNumber(), + expiryTime + duration.days(200), + true, + false, + validFrom, + validTo, + nonce, + sig, + { + from: account_investor2, + gas: 6000000 + } + ) + + }); + + it("Should fail in changing the signing address", async () => { + await catchRevert(I_GeneralTransferManager.changeSigningAddress(account_polymath, { from: account_investor4 })); + }); + + 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 fail to pull fees as no budget set", async () => { + await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_polymath })); + }); + + it("Should set a budget for the GeneralTransferManager", async () => { + await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, new BN(10).pow(new BN(19)), true, { from: token_owner }); + + await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: token_owner })); + await I_PolyToken.getTokens(new BN(10).pow(new BN(19)), token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(10).pow(new BN(19)), { from: token_owner }); + }); + + it("Factory owner should pull fees - fails as not permissioned by issuer", async () => { + await catchRevert(I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate })); + }); + + it("Factory owner should pull fees", async () => { + await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("FEE_ADMIN"), true, { + from: token_owner + }); + let balanceBefore = await I_PolyToken.balanceOf(account_polymath); + await I_GeneralTransferManager.takeFee(new BN(web3.utils.toWei("1", "ether")), { from: account_delegate }); + let balanceAfter = await I_PolyToken.balanceOf(account_polymath); + assert.equal(balanceBefore.add(new BN(web3.utils.toWei("1", "ether"))).toString(), balanceAfter.toString(), "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 }); + await catchRevert(I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 })); + }); + + 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 = await latestTime(); + let toTime = await latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime, toTime], + [expiryTime, expiryTime], + [true, true], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ) + ); + }); + + it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime], + [toTime, toTime], + [expiryTime, expiryTime], + [1, 1], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ) + ); + }); + + it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime], + [expiryTime, expiryTime], + [true, true], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ) + ); + }); + + it("Should fail in adding the investors in whitelist -- array length mismatch", async () => { + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + await catchRevert( + I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime, toTime], + [expiryTime], + [true, true], + [true, true], + { + from: account_delegate, + gas: 6000000 + } + ) + ); + }); + + it("Should successfully add the investors in whitelist", async () => { + let fromTime = await latestTime(); + let toTime = await latestTime() + duration.days(20); + let expiryTime = toTime + duration.days(10); + + let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + [account_investor3, account_investor4], + [fromTime, fromTime], + [toTime, toTime], + [expiryTime, expiryTime], + [true, true], + [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.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, ""), + "GeneralTransferManager", + "Wrong Module added" + ); + assert.equal( + await I_GeneralTransferManagerFactory.description.call(), + "Manage transfers using a time based whitelist", + "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.", + "Wrong Module added" + ); + assert.equal(await I_GeneralTransferManagerFactory.version.call(), "2.1.0"); + }); + + 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.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.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"); + }); + + 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"); + }); + + it("Should get the version of factory", async () => { + let version = await I_DummySTOFactory.version.call(); + assert.equal(version, "1.0.0"); + }); + }); + + 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)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + }); + + it("Should get the raised amount of poly", async () => { + assert.equal((await I_DummySTO.getRaised.call(1)).toString(), new BN(web3.utils.toWei("0", "ether")).toString()); + }); + + it("Should get the investors", async () => { + assert.equal((await I_DummySTO.getNumberInvestors.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"); + }); + + it("Should get the amount of tokens sold", async () => { + assert.equal(await I_DummySTO.getTokensSold.call(), 0); + }); + }); }); function range1(i) { diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 3acbc6d4c..73a2ff761 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -27,8 +27,8 @@ function getSignSTMData(tmAddress, nonce, expiry, fromAddress, toAddress, amount return data; } -function getSignGTMData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { - let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: investorAddress}, {t: 'uint256', v: new BN(fromTime)}, {t: 'uint256', v: new BN(toTime)}, {t: 'uint256', v: new BN(expiryTime)}, {t: 'bool', v: restricted}, {t: 'uint256', v: new BN(validFrom)}, {t: 'uint256', v: new BN(validTo)}, {t: 'uint256', v: new BN(nonce)}); +function getSignGTMData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, accredited, validFrom, validTo, nonce, pk) { + let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: investorAddress}, {t: 'uint256', v: new BN(fromTime)}, {t: 'uint256', v: new BN(toTime)}, {t: 'uint256', v: new BN(expiryTime)}, {t: 'bool', v: restricted}, {t: 'bool', v: accredited}, {t: 'uint256', v: new BN(validFrom)}, {t: 'uint256', v: new BN(validTo)}, {t: 'uint256', v: new BN(nonce)}); let signature = (web3.eth.accounts.sign(hash, pk)); return signature.signature; } From 1a88d66293a2581decd72b1babbbaad5f7a06a96 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 5 Feb 2019 18:11:00 +0530 Subject: [PATCH 098/119] cleanup --- contracts/interfaces/IBoot.sol | 1 - .../modules/PermissionManager/GeneralPermissionManager.sol | 2 -- .../modules/TransferManager/GeneralTransferManagerFactory.sol | 1 - contracts/tokens/SecurityToken.sol | 1 - 4 files changed, 5 deletions(-) diff --git a/contracts/interfaces/IBoot.sol b/contracts/interfaces/IBoot.sol index 437a24523..34d3c3fc1 100644 --- a/contracts/interfaces/IBoot.sol +++ b/contracts/interfaces/IBoot.sol @@ -7,5 +7,4 @@ interface IBoot { */ function getInitFunction() external pure returns(bytes4); - function initialize() external; } \ No newline at end of file diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 9281145f2..6ce855897 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -27,8 +27,6 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio return bytes4(0); } - function initialize() public {} - /** * @notice Used to check the permission on delegate corresponds to module contract address * @param _delegate Ethereum address of the delegate diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 52d60366a..434311e34 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -2,7 +2,6 @@ pragma solidity ^0.5.0; import "../../proxy/GeneralTransferManagerProxy.sol"; import "../ModuleFactory.sol"; -import "../../interfaces/IBoot.sol"; /** * @title Factory for deploying GeneralTransferManager module diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 12bcd91a1..7e7e14ba2 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/Math.sol"; -import "../interfaces/IBoot.sol"; import "../interfaces/IPoly.sol"; import "../interfaces/IModule.sol"; import "../interfaces/IModuleFactory.sol"; From ec54ae81971933a905f6ccfc7e7d0a64ddf54eb2 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 5 Feb 2019 18:44:33 +0530 Subject: [PATCH 099/119] fix test and changelog --- 0 | 0 CHANGELOG.md | 24 +++++++-------- test/b_capped_sto.js | 10 ++++--- test/c_checkpoints.js | 3 ++ test/d_count_transfer_manager.js | 8 +++++ test/e_erc20_dividends.js | 4 +++ test/f_ether_dividends.js | 5 ++++ test/i_Issuance.js | 3 +- test/j_manual_approval_transfer_manager.js | 3 ++ test/l_percentage_transfer_manager.js | 3 ++ test/m_presale_sto.js | 6 ++-- test/o_security_token.js | 20 +++++++------ test/p_usd_tiered_sto.js | 30 +++++++++---------- test/q_usd_tiered_sto_sim.js | 10 +++---- test/r_concurrent_STO.js | 2 +- test/v_tracked_redemptions.js | 2 ++ test/w_lockup_transfer_manager.js | 3 ++ test/x_scheduled_checkpoints.js | 3 ++ test/y_volume_restriction_tm.js | 2 ++ test/z_blacklist_transfer_manager.js | 5 ++++ ...zer_volumn_restriction_transfer_manager.js | 1 + test/z_general_permission_manager_fuzzer.js | 6 ++-- test/z_vesting_escrow_wallet.js | 2 ++ test/zb_signed_transfer_manager.js | 1 + 24 files changed, 103 insertions(+), 53 deletions(-) delete mode 100644 0 diff --git a/0 b/0 deleted file mode 100644 index e69de29bb..000000000 diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ad6a93a..c5e428e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,29 @@ # Changelog All notable changes to this project will be documented in this file. -# v3.0.0 - -[__3.0.0__] - -## Changed -* Changed the first three params in Security Token `event ModuleAdded()` to be indexed for search. Params are `unit8[] types`, `bytes32 _name` and `address _moduleFactory` - # v3.0.0 - Release Candidate [__3.0.0__](https://www.npmjs.com/package/polymath-core?activeTab=readme) __10-11-18__ -## Added +## SecurityToken * Added new function `addModuleWithLabel()` which takes an extra param `_label` that used for giving the customize label to the module for display purpose. #428 -* Introduce new contract `STRGetter.sol`. It only contains the getter functions of the STR. - -## Fixed +* Changed the first three params in Security Token `event ModuleAdded()` to be indexed for search. Params are `unit8[] types`, `bytes32 _name` and `address _moduleFactory` * Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. * Fixed event `ModuleAdded` to also emit `_label`. * Fixed function `getModule` to also return the respective module label. + +## STR +* Introduce new contract `STRGetter.sol`. It only contains the getter functions of the STR. * Replaced `updatePolyTokenAddress()` function with `updateFromRegistry()` in `SecurityTokenRegistry`. * Migrate all the getters of `SecurityTokenRegsitry.sol` to `STRGetter.sol` contract. +* Removed `_polyToken` parameter from `initialize` function in `SecurityTokenRegistry`. -## Removed +## GeneralTransferManager +* Add `_isAccredited` variable in the `modifyWhitelist()` function of the GeneralTransferManager. + +## Generalize * Removed `_polyAddress` parameter from constructors of all modules and module factories. -* Removed `_polyToken` parameter from `initialize` function in `SecurityTokenRegistry`. + # v2.1.0 - Release Candidate diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d98271c7e..4cb9fd084 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -315,7 +315,7 @@ contract("CappedSTO", async (accounts) => { P_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, true, false, { from: account_issuer }); @@ -391,6 +391,7 @@ contract("CappedSTO", async (accounts) => { toTime + duration.days(20), expiryTime, true, + false, { from: account_issuer } @@ -529,7 +530,7 @@ contract("CappedSTO", async (accounts) => { it("Should successfully whitelist investor 3", async () => { balanceOfReceiver = new BN(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, true, false, { from: account_issuer, gas: 500000 }); @@ -694,7 +695,7 @@ contract("CappedSTO", async (accounts) => { 10500, "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, true, false, { from: account_issuer, gas: 500000 }); @@ -758,6 +759,7 @@ contract("CappedSTO", async (accounts) => { P_toTime + duration.days(20), P_expiryTime, true, + false, { from: account_issuer, gas: 500000 @@ -967,7 +969,7 @@ contract("CappedSTO", async (accounts) => { await I_PolyToken.getTokens(polyToInvest.mul(new BN(10).pow(new BN(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, true, false, { from: account_issuer, gas: 500000 }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index d50620db6..3529d350c 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -154,6 +154,7 @@ contract("Checkpoints", async function(accounts) { ltime, ltime.add(new BN(duration.days(10))), false, + false, { from: account_issuer, gas: 6000000 @@ -180,6 +181,7 @@ contract("Checkpoints", async function(accounts) { ltime, ltime.add(new BN(duration.days(10))), false, + false, { from: account_issuer, gas: 6000000 @@ -206,6 +208,7 @@ contract("Checkpoints", async function(accounts) { ltime, ltime.add(new BN(duration.days(10))), false, + false, { from: account_issuer, gas: 6000000 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index d6de7c581..75fa83426 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -206,6 +206,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -236,6 +237,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -263,6 +265,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -288,6 +291,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -376,6 +380,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -388,6 +393,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -400,6 +406,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 @@ -412,6 +419,7 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 500000 diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index f17bd200a..b0ab30d82 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -215,6 +215,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(30))), true, + false, { from: account_issuer, gas: 500000 @@ -245,6 +246,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(30))), true, + false, { from: account_issuer, gas: 500000 @@ -391,6 +393,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(20))), true, + false, { from: account_issuer, gas: 500000 @@ -454,6 +457,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(100000))), true, + false, { from: account_issuer, gas: 500000 diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index dae87c572..fab59b140 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -209,6 +209,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(300000))), true, + false, { from: account_issuer, gas: 500000 @@ -239,6 +240,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(3000000))), true, + false, { from: account_issuer, gas: 500000 @@ -373,6 +375,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(200000))), true, + false, { from: account_issuer, gas: 500000 @@ -424,6 +427,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10000))), true, + false, { from: account_issuer, gas: 500000 @@ -730,6 +734,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(1000000))), true, + false, { from: account_issuer, gas: 500000 diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 7b62336bd..88ef45ee7 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -210,6 +210,7 @@ contract("Issuance", async (accounts) => { toTime + duration.days(90), expiryTime + duration.days(50), true, + false, { from: account_polymath } @@ -269,7 +270,7 @@ contract("Issuance", async (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, true, false, { from: account_delegate, gas: 7000000 }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 26580b093..375730459 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -176,6 +176,7 @@ contract("ManualApprovalTransferManager", accounts => { currentTime, currentTime.add(new BN(duration.days(30))), true, + false, { from: account_issuer, gas: 6000000 @@ -206,6 +207,7 @@ contract("ManualApprovalTransferManager", accounts => { currentTime, currentTime.add(new BN(duration.days(30))), true, + false, { from: account_issuer, gas: 6000000 @@ -295,6 +297,7 @@ contract("ManualApprovalTransferManager", accounts => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index b27f34427..5867ecdfa 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -203,6 +203,7 @@ contract("PercentageTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 @@ -233,6 +234,7 @@ contract("PercentageTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 @@ -298,6 +300,7 @@ contract("PercentageTransferManager", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index daa982397..a2c84a3eb 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -241,7 +241,7 @@ contract("PreSaleSTO", async (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, true, false, { from: account_issuer, gas: 6000000 }); @@ -282,7 +282,7 @@ contract("PreSaleSTO", async (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, true, false, { from: account_issuer, gas: 6000000 }); @@ -290,7 +290,7 @@ contract("PreSaleSTO", async (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, true, false, { from: account_issuer, gas: 6000000 }); diff --git a/test/o_security_token.js b/test/o_security_token.js index d6adbbc99..082629e60 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -198,7 +198,7 @@ contract("SecurityToken", async (accounts) => { let toTime = new BN(currentTime.add(new BN(duration.days(100)))); let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, currentTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, currentTime, toTime, expiryTime, true, false, { from: token_owner, gas: 6000000 }); @@ -217,7 +217,7 @@ contract("SecurityToken", async (accounts) => { let toTime = new BN(currentTime.add(new BN(duration.days(100)))); let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, currentTime, toTime, expiryTime, true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, currentTime, toTime, expiryTime, true, false, { from: token_owner, gas: 6000000 }); @@ -535,7 +535,7 @@ contract("SecurityToken", async (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, true, false, { from: token_owner, gas: 6000000 }); @@ -647,7 +647,7 @@ contract("SecurityToken", async (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, true, false, { from: token_owner, gas: 500000 }); @@ -669,7 +669,7 @@ contract("SecurityToken", async (accounts) => { it("Should transferFrom from one investor to other", async () => { await I_SecurityToken.approve(account_investor1, new BN(2).mul(new BN(10).pow(new BN(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, true, false, { from: token_owner, gas: 500000 }); @@ -714,7 +714,7 @@ contract("SecurityToken", async (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, true, false, { from: account_delegate, gas: 6000000 }); @@ -754,7 +754,7 @@ contract("SecurityToken", async (accounts) => { }); it("Should remove investor from the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, new BN(0), new BN(0), new BN(0), true, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, new BN(0), new BN(0), new BN(0), true, false, { from: account_delegate, gas: 6000000 }); @@ -783,7 +783,7 @@ contract("SecurityToken", async (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, true, false, { from: account_delegate, gas: 6000000 }); @@ -969,7 +969,8 @@ contract("SecurityToken", async (accounts) => { currentTime, currentTime.add(new BN(duration.seconds(2))), currentTime.add(new BN(duration.days(50))), - true, + true, + false, { from: account_delegate, gas: 6000000 @@ -1012,6 +1013,7 @@ contract("SecurityToken", async (accounts) => { currentTime.add(new BN(duration.seconds(2))), currentTime.add(new BN(duration.days(50))), true, + false, { from: account_delegate, gas: 6000000 diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 4661fb043..f84b72365 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1010,8 +1010,8 @@ contract("USDTieredSTO", async (accounts) => { 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(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); // // Advance time to after STO start // await increaseTime(duration.days(3)); @@ -1110,8 +1110,8 @@ contract("USDTieredSTO", async (accounts) => { 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(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); // Advance time to after STO start await increaseTime(duration.days(3)); @@ -1165,8 +1165,8 @@ contract("USDTieredSTO", async (accounts) => { 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(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,false, { from: ISSUER }); // Advance time to after STO start await increaseTime(duration.days(3)); @@ -1235,8 +1235,8 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime.add(new BN(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(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); // Advance time to after STO start await increaseTime(duration.days(3)); @@ -1282,8 +1282,8 @@ contract("USDTieredSTO", async (accounts) => { 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(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); // Advance time to after STO end await increaseTime(duration.days(3)); @@ -1337,9 +1337,9 @@ contract("USDTieredSTO", async (accounts) => { 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 }); + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(RESERVEWALLET, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); // Advance time to after STO start await increaseTime(duration.days(3)); @@ -1405,11 +1405,11 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, { + const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { 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, { + const tx2 = await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); assert.equal(tx2.logs[0].args._investor, ACCREDITED1, "Failed in adding the investor in whitelist"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index e4f9db8e1..2fbd6c411 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -372,11 +372,11 @@ contract("USDTieredSTO Sim", async (accounts) => { 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 I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, false, { from: ISSUER }); await increaseTime(duration.days(3)); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 129116c26..9fb77c22c 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -166,7 +166,7 @@ contract("Concurrent STO", async (accounts) => { let expiryTime = toTime + duration.days(100); let canBuyFromSTO = true; - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, { + let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, false, { from: account_issuer, gas: 500000 }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 28ccaded7..1629a09c7 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -193,6 +193,7 @@ contract("TrackedRedemption", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(30))), true, + false, { from: account_issuer, gas: 500000 @@ -223,6 +224,7 @@ contract("TrackedRedemption", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(30))), true, + false, { from: account_issuer, gas: 500000 diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 0be2bfe04..fd2d6668f 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -203,6 +203,7 @@ contract('LockUpTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer }); @@ -230,6 +231,7 @@ contract('LockUpTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer }); @@ -300,6 +302,7 @@ contract('LockUpTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer }); diff --git a/test/x_scheduled_checkpoints.js b/test/x_scheduled_checkpoints.js index aa490f32e..8c09930ac 100644 --- a/test/x_scheduled_checkpoints.js +++ b/test/x_scheduled_checkpoints.js @@ -183,6 +183,7 @@ contract("ScheduledCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 @@ -228,6 +229,7 @@ contract("ScheduledCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 @@ -264,6 +266,7 @@ contract("ScheduledCheckpoint", async (accounts) => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer, gas: 6000000 diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 0b5456a0d..14fef9080 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -230,6 +230,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [newLatestTime, newLatestTime, newLatestTime], [newLatestTime.add(new BN(duration.days(60))), newLatestTime.add(new BN(duration.days(60))), newLatestTime.add(new BN(duration.days(60)))], [true, true, true], + [false,false,false], { from: token_owner } @@ -1304,6 +1305,7 @@ contract('VolumeRestrictionTransferManager', accounts => { newLatestTime, newLatestTime.add(new BN(duration.days(30))), true, + false, { from: token_owner } diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index 54e249a1f..50be454d9 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -220,6 +220,7 @@ contract('BlacklistTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(50))), true, + false, { from: account_issuer }); @@ -247,6 +248,7 @@ contract('BlacklistTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(50))), true, + false, { from: account_issuer }); @@ -271,6 +273,7 @@ contract('BlacklistTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(50))), true, + false, { from: account_issuer }); @@ -295,6 +298,7 @@ contract('BlacklistTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(50))), true, + false, { from: account_issuer }); @@ -319,6 +323,7 @@ contract('BlacklistTransferManager', accounts => { currentTime, currentTime.add(new BN(duration.days(50))), true, + false, { from: account_issuer }); diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 0cf2fc02f..0444bb18a 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -218,6 +218,7 @@ contract('VolumeRestrictionTransferManager', accounts => { [currentTime, currentTime, currentTime], [currentTime.add(new BN(duration.days(60))), currentTime.add(new BN(duration.days(60))), currentTime.add(new BN(duration.days(60)))], [true, true, true], + [false, false, false], { from: token_owner } diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 7f7933801..10227edc6 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -353,7 +353,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { console.log("3"); if (randomPerms === "WHITELIST") { - let tx = await I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, { + let tx = await I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, false, { from: accounts[j] }); assert.equal(tx.logs[0].args._investor, accounts[j]); @@ -364,6 +364,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { [toTime, toTime], [expiryTime, expiryTime], [1, 1], + [false, false], { from: accounts[j] } ); console.log(tx2.logs[1].args); @@ -372,7 +373,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { } else { console.log("3.3"); await catchRevert( - I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, { from: accounts[j] }) + I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, false, { from: accounts[j] }) ); console.log("3.4"); await catchRevert( @@ -382,6 +383,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { [toTime, toTime], [expiryTime, expiryTime], [1, 1], + [false, false], { from: accounts[j] } ) ); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index b5aba3441..df61d62a6 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -199,6 +199,7 @@ contract('VestingEscrowWallet', accounts => { currentTime, currentTime.add(new BN(durationUtil.days(10))), true, + false, { from: token_owner, gas: 6000000 @@ -225,6 +226,7 @@ contract('VestingEscrowWallet', accounts => { [currentTime, currentTime, currentTime, currentTime], [currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10)))], [true, true, true, true], + [false, false, false, false], { from: token_owner, gas: 6000000 diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index a35baba07..e0b80bbe6 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -166,6 +166,7 @@ contract("SignedTransferManager", accounts => { currentTime, currentTime.add(new BN(duration.days(10))), true, + false, { from: account_issuer } From b2cbf3c519507204dc8af6ba0c1ba9581104f6f8 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 6 Feb 2019 11:18:47 +0530 Subject: [PATCH 100/119] change packing --- contracts/libraries/VersionUtils.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 88ca792ed..8375cde68 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -111,7 +111,7 @@ library VersionUtils { * @notice Used to packed the KYC data */ function packKYC(uint64 _a, uint64 _b, uint64 _c, uint8 _d, uint8 _e, uint8 _f) internal pure returns(uint256) { - return (uint256(_a) << 184) | (uint256(_b) << 120) | (uint256(_c) << 56) | (uint256(_d) << 24) | (uint256(_e) << 16) | uint256(_f); + return (uint256(_a) << 152) | (uint256(_b) << 88) | (uint256(_c) << 24) | (uint256(_d) << 16) | (uint256(_e) << 8) | uint256(_f); } /** @@ -119,11 +119,11 @@ library VersionUtils { * @param _packedVersion Packed data */ function unpackKYC(uint256 _packedVersion) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added, uint8 accredited) { - fromTime = uint64(_packedVersion >> 184); - toTime = uint64(_packedVersion >> 120); - expiryTime = uint64(_packedVersion >> 56); - canBuy = uint8(_packedVersion >> 24); - added = uint8(_packedVersion >> 16); + fromTime = uint64(_packedVersion >> 152); + toTime = uint64(_packedVersion >> 88); + expiryTime = uint64(_packedVersion >> 24); + canBuy = uint8(_packedVersion >> 16); + added = uint8(_packedVersion >> 8); accredited = uint8(_packedVersion); } From c1c4c485342a3ad0a6e5c1d919c9d7abb1ddeb04 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 6 Feb 2019 12:29:59 +0530 Subject: [PATCH 101/119] to fix the coverage --- test/h_general_transfer_manager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index bbb3d4c66..e80c29995 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -251,17 +251,17 @@ contract("GeneralTransferManager", async (accounts) => { it("Should whitelist lots of addresses and check gas", async () => { let mockInvestors = []; - for (let i = 0; i < 100; i++) { + for (let i = 0; i < 50; i++) { mockInvestors.push("0x1000000000000000000000000000000000000000".substring(0, 42 - i.toString().length) + i.toString()); } - let times = range1(100); - let bools = rangeB(100); + let times = range1(50); + let bools = rangeB(50); let tx = await I_GeneralTransferManager.modifyWhitelistMulti(mockInvestors, times, times, times, bools, bools, { from: account_issuer, gas: 7900000 }); - console.log("Multi Whitelist x 100: " + tx.receipt.gasUsed); + console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); assert.deepEqual( await I_GeneralTransferManager.getInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors) From aa31239a8e7106e47ea1138d6f44a971e9d7e706 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 6 Feb 2019 09:13:38 -0400 Subject: [PATCH 102/119] Minor function naming updates --- .../GeneralTransferManager.sol | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 6b2f56651..361b8e6e7 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -154,7 +154,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage bool /* _isTransfer */ ) external returns(Result) { if (!paused) { - uint64 fromTime; + uint64 fromTime; uint64 fromExpiry; uint64 toExpiry; uint64 toTime; @@ -167,11 +167,11 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return Result.VALID; } - (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValuesToUser(_from, _to); + (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValuesForTransfer(_from, _to); if (allowAllWhitelistTransfers) { //Anyone on the whitelist can transfer, regardless of time - return (_onWhitelist(toExpiry) && _onWhitelist(fromExpiry)) ? Result.VALID : Result.NA; + return (_validExpiry(toExpiry) && _validExpiry(fromExpiry)) ? Result.VALID : Result.NA; } // Using the local variables to avoid the stack too deep error (fromTime, toTime) = _adjustTimes(fromTime, toTime); @@ -182,16 +182,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage } // if allowAllWhitelistIssuances is true, so time stamp ignored if (allowAllWhitelistIssuances) { - return _onWhitelist(toExpiry) ? Result.VALID : Result.NA; + return _validExpiry(toExpiry) ? Result.VALID : Result.NA; } else { - return (_onWhitelist(toExpiry) && (toTime <= uint64(now))) ? Result.VALID : Result.NA; + return (_validExpiry(toExpiry) && _validLockTime(toTime)) ? 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(fromExpiry) && (fromTime <= uint64(now))) && (_onWhitelist(toExpiry) && - (toTime <= uint64(now)))) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return (_validExpiry(fromExpiry) && _validLockTime(fromTime) && _validExpiry(toExpiry) && + _validLockTime(toTime)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ } return Result.NA; } @@ -232,15 +232,15 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(_investor != address(0), "Invalid investor"); uint8 added; uint8 canBuyFromSTO; - uint8 accredited; + uint8 isAccredited; IDataStore dataStore = IDataStore(getDataStore()); (,,,,added,) = _getValues(_investor, dataStore); if (added == uint8(0)) { investors.push(_investor); } canBuyFromSTO = _canBuyFromSTO ? 1 : 0; - accredited = _isAccredited ? 1 : 0; - uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1), accredited); + isAccredited = _isAccredited ? 1 : 0; + uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1), isAccredited); dataStore.setUint256(_getKey(WHITELIST, _investor), _data); emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); } @@ -261,7 +261,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256[] memory _expiryTimes, bool[] memory _canBuyFromSTO, bool[] memory _isAccredited - ) + ) public withPerm(WHITELIST) { @@ -329,14 +329,21 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage } /** - * @notice Internal function used to check whether the investor is in the whitelist or not - & also checks whether the KYC of investor get expired or not + * @notice Internal function used to check whether the KYC of investor is valid * @param _expiryTime Expiry time of the investor */ - function _onWhitelist(uint64 _expiryTime) internal view returns(bool) { + function _validExpiry(uint64 _expiryTime) internal view returns(bool) { return (_expiryTime >= uint64(now)); /*solium-disable-line security/no-block-members*/ } + /** + * @notice Internal function used to check whether the lock time of investor is valid + * @param _lockTime Lock time of the investor + */ + function _validLockTime(uint64 _lockTime) internal view returns(bool) { + return (_lockTime <= uint64(now)); /*solium-disable-line security/no-block-members*/ + } + /** * @notice Internal function use to know whether the STO is attached or not */ @@ -371,13 +378,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint8 canBuyFromSTO, uint8 added, uint8 isAccredited - ) + ) { uint256 _whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); (fromTime, toTime, expiryTime, canBuyFromSTO, added, isAccredited) = VersionUtils.unpackKYC(_whitelistData); } - function _getValuesToUser(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry) { + function _getValuesForTransfer(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry) { IDataStore dataStore = IDataStore(getDataStore()); (fromTime,, fromExpiry,,,) = _getValues(_from, dataStore); (, toTime, toExpiry, canBuyFromSTO,,) = _getValues(_to, dataStore); From 28f0652da1c6cb3a6dc0f17422578ebc698a99ab Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 6 Feb 2019 18:58:09 +0530 Subject: [PATCH 103/119] Optimized modifyWhitelist --- .../modules/TransferManager/GeneralTransferManager.sol | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 361b8e6e7..0139291ef 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -234,7 +234,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint8 canBuyFromSTO; uint8 isAccredited; IDataStore dataStore = IDataStore(getDataStore()); - (,,,,added,) = _getValues(_investor, dataStore); + added = _getAddedValue(_investor, dataStore); if (added == uint8(0)) { investors.push(_investor); } @@ -384,6 +384,12 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage (fromTime, toTime, expiryTime, canBuyFromSTO, added, isAccredited) = VersionUtils.unpackKYC(_whitelistData); } + function _getAddedValue(address _investor, IDataStore dataStore) internal view returns(uint8) { + uint256 _whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); + //extracts `added` from packed `_whitelistData` + return uint8(_whitelistData >> 8); + } + function _getValuesForTransfer(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry) { IDataStore dataStore = IDataStore(getDataStore()); (fromTime,, fromExpiry,,,) = _getValues(_from, dataStore); From 25e8f0e90ad1ed422742055a767705720d686cc0 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Wed, 6 Feb 2019 09:31:33 -0400 Subject: [PATCH 104/119] Use USD in place of POLY (#539) * WIP * Remove old file * Fix migrations * Fixes and test cases * Some fixes * Fix lots of tests * More fixes * Update lots more tests * Update comments --- contracts/PolymathRegistry.sol | 2 +- contracts/SecurityTokenRegistry.sol | 59 ++++++++++------- contracts/interfaces/IModuleFactory.sol | 23 ++++--- contracts/mocks/MockBurnFactory.sol | 19 +++--- contracts/mocks/MockFactory.sol | 12 ++-- contracts/mocks/MockWrongTypeFactory.sol | 10 +-- contracts/mocks/TestSTOFactory.sol | 12 ++-- .../ERC20DividendCheckpointFactory.sol | 10 +-- .../EtherDividendCheckpointFactory.sol | 10 +-- .../Burn/TrackedRedemptionFactory.sol | 20 +++--- .../Mixed/ScheduledCheckpointFactory.sol | 53 +++------------- .../BlacklistTransferManagerFactory.sol | 8 +-- .../KYCTransferManagerFactory.sol | 10 +-- .../LockUpTransferManagerFactory.sol | 8 +-- .../SignedTransferManagerFactory.sol | 41 +----------- .../Wallet/VestingEscrowWalletFactory.sol | 6 +- contracts/modules/ModuleFactory.sol | 63 ++++++++++--------- .../GeneralPermissionManagerFactory.sol | 20 +++--- contracts/modules/STO/CappedSTOFactory.sol | 16 ++--- contracts/modules/STO/DummySTOFactory.sol | 14 ++--- contracts/modules/STO/PreSaleSTOFactory.sol | 14 ++--- contracts/modules/STO/USDTieredSTOFactory.sol | 11 ++-- .../CountTransferManagerFactory.sol | 15 +++-- .../GeneralTransferManagerFactory.sol | 20 +++--- .../ManualApprovalTransferManagerFactory.sol | 10 +-- .../PercentageTransferManagerFactory.sol | 15 +++-- .../VolumeRestrictionTMFactory.sol | 10 ++- contracts/tokens/SecurityToken.sol | 2 +- migrations/2_deploy_contracts.js | 20 +++--- test/b_capped_sto.js | 30 +++++---- test/c_checkpoints.js | 2 +- test/d_count_transfer_manager.js | 33 ++++------ test/e_erc20_dividends.js | 10 +-- test/f_ether_dividends.js | 10 +-- test/g_general_permission_manager.js | 12 ++-- test/h_general_transfer_manager.js | 16 ++--- test/helpers/createInstances.js | 59 ++++++++++------- test/i_Issuance.js | 11 ++-- test/j_manual_approval_transfer_manager.js | 10 +-- test/k_module_registry.js | 22 +++---- test/l_percentage_transfer_manager.js | 10 +-- test/m_presale_sto.js | 2 +- test/n_security_token_registry.js | 54 ++++++++-------- test/o_security_token.js | 22 ++++--- test/p_usd_tiered_sto.js | 8 +-- test/q_usd_tiered_sto_sim.js | 4 +- test/r_concurrent_STO.js | 11 ++-- test/t_security_token_registry_proxy.js | 7 ++- test/u_module_registry_proxy.js | 5 +- test/v_tracked_redemptions.js | 8 +-- test/w_lockup_transfer_manager.js | 10 +-- test/x_scheduled_checkpoints.js | 4 +- test/y_volume_restriction_tm.js | 2 +- test/z_blacklist_transfer_manager.js | 10 +-- .../z_fuzz_test_adding_removing_modules_ST.js | 10 +-- ...zer_volumn_restriction_transfer_manager.js | 2 +- test/z_general_permission_manager_fuzzer.js | 10 +-- test/z_vesting_escrow_wallet.js | 4 +- test/za_datastore.js | 6 +- test/zb_signed_transfer_manager.js | 4 +- 60 files changed, 454 insertions(+), 487 deletions(-) diff --git a/contracts/PolymathRegistry.sol b/contracts/PolymathRegistry.sol index 15e34ff6f..f80144b43 100644 --- a/contracts/PolymathRegistry.sol +++ b/contracts/PolymathRegistry.sol @@ -17,7 +17,7 @@ contract PolymathRegistry is ReclaimTokens { */ function getAddress(string calldata _nameKey) external view returns(address) { bytes32 key = keccak256(bytes(_nameKey)); - require(storedAddresses[key] != address(0), "Invalid address key"); + require(storedAddresses[key] != address(0), "Invalid key"); return storedAddresses[key]; } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 60c085e72..dfd7eca32 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -11,6 +11,8 @@ import "./libraries/Util.sol"; import "./libraries/Encoder.sol"; import "./libraries/VersionUtils.sol"; import "./proxy/Proxy.sol"; +import "./interfaces/IOracle.sol"; +import "./libraries/DecimalMath.sol"; /** * @title Registry contract for issuers to register their tickers and security tokens @@ -74,6 +76,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { bytes32 constant POLYMATHREGISTRY = 0x90eeab7c36075577c7cc5ff366e389fefa8a18289b949bab3529ab4471139d4d; bytes32 constant STRGETTER = 0x982f24b3bd80807ec3cb227ba152e15c07d66855fa8ae6ca536e689205c0e2e9; + string constant POLY_ORACLE = "PolyUsdOracle"; + // Emit when network becomes paused event Pause(uint256 _timestammp); // Emit when network becomes unpaused @@ -99,7 +103,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { uint256 _addedAt, address _registrant, bool _fromAdmin, - uint256 _registrationFee + uint256 _usdFee, + uint256 _polyFee ); // Emit after ticker registration event RegisterTicker( @@ -109,7 +114,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { uint256 indexed _registrationDate, uint256 indexed _expiryDate, bool _fromAdmin, - uint256 _registrationFee + uint256 _usdFee, + uint256 _polyFee ); ///////////////////////////// @@ -159,8 +165,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { * @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 - * @param _tickerRegFee is the fee in POLY required to register a ticker + * @param _stLaunchFee is the fee in USD required to launch a token + * @param _tickerRegFee is the fee in USD required to register a ticker * @param _owner is the owner of the STR, * @param _getterContract Contract address of the contract which consists getter functions. */ @@ -205,6 +211,19 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { set(POLYTOKEN, IPolymathRegistry(polymathRegistry).getAddress("PolyToken")); } + /** + * @notice Converts USD fees into POLY amounts + */ + function _takeFee(bytes32 _feeType) internal returns (uint256, uint256){ + address polymathRegistry = getAddressValue(POLYMATHREGISTRY); + uint256 polyRate = IOracle(IPolymathRegistry(polymathRegistry).getAddress(POLY_ORACLE)).getPrice(); + uint256 usdFee = getUintValue(_feeType); + uint256 polyFee = DecimalMath.div(usdFee, polyRate); + if (polyFee > 0) + require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), polyFee), "Insufficent allowance"); + return (usdFee, polyFee); + } + /** * @notice Set the getter contract address * @param _getterContract Address of the contract @@ -233,10 +252,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { function registerTicker(address _owner, string calldata _ticker, string calldata _tokenName) external whenNotPausedOrOwner { require(_owner != address(0), "Owner should not be 0x"); require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); - // Attempt to charge the reg fee if it is > 0 POLY - uint256 tickerFee = getUintValue(TICKERREGFEE); - if (tickerFee > 0) - require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), tickerFee), "Insufficent allowance"); + // Attempt to charge the reg fee if it is > 0 USD + (uint256 _usdFee, uint256 _polyFee) = _takeFee(TICKERREGFEE); string memory ticker = Util.upper(_ticker); require(_tickerAvailable(ticker), "Ticker is reserved"); // Check whether ticker was previously registered (and expired) @@ -245,7 +262,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _deleteTickerOwnership(previousOwner, ticker); } /*solium-disable-next-line security/no-block-members*/ - _addTicker(_owner, ticker, _tokenName, now, now.add(getUintValue(EXPIRYLIMIT)), false, false, tickerFee); + _addTicker(_owner, ticker, _tokenName, now, now.add(getUintValue(EXPIRYLIMIT)), false, false, _usdFee, _polyFee); } /** @@ -259,13 +276,14 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { uint256 _expiryDate, bool _status, bool _fromAdmin, - uint256 _fee + uint256 _usdFee, + uint256 _polyFee ) internal { _setTickerOwnership(_owner, _ticker); _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _usdFee, _polyFee); } /** @@ -321,7 +339,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { if (_status) { require(getAddressValue(Encoder.getKey("tickerToSecurityToken", _ticker)) != address(0), "Token not registered"); } - _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0)); + _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0), uint256(0)); } function _tickerOwner(string memory _ticker) internal view returns(address) { @@ -478,10 +496,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { require(_tickerOwner(ticker) == msg.sender, "Not authorised"); /*solium-disable-next-line security/no-block-members*/ require(getUintValue(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); - - uint256 launchFee = getUintValue(STLAUNCHFEE); - if (launchFee > 0) - require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); + (uint256 _usdFee, uint256 _polyFee) = _takeFee(STLAUNCHFEE); address newSecurityTokenAddress = ISTFactory(getAddressValue(Encoder.getKey("protocolVersionST", getUintValue(Encoder.getKey("latestVersion"))))).deployToken( _name, @@ -497,7 +512,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { _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); + emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false, _usdFee, _polyFee); } /** @@ -535,7 +550,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); - emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getUintValue(STLAUNCHFEE)); + emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, uint256(0), uint256(0)); } /** @@ -594,8 +609,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { } /** - * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. - * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) + * @notice Sets the ticker registration fee in USD tokens. Only Polymath. + * @param _tickerRegFee is the registration fee in USD tokens (base 18 decimals) */ function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { uint256 fee = getUintValue(TICKERREGFEE); @@ -605,8 +620,8 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { } /** - * @notice Sets the ticker registration fee in POLY tokens. Only Polymath. - * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) + * @notice Sets the ticker registration fee in USD tokens. Only Polymath. + * @param _stLaunchFee is the registration fee in USD tokens (base 18 decimals) */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { uint256 fee = getUintValue(STLAUNCHFEE); diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index d0a35355d..9af977287 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -4,15 +4,15 @@ pragma solidity ^0.5.0; * @title Interface that every module factory contract should implement */ interface IModuleFactory { - 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 ChangeSetupCost(uint256 _oldSetupCost, uint256 _newSetupCost); + event ChangeUsageCost(uint256 _oldUsageCost, uint256 _newUsageCost); event GenerateModuleFromFactory( address _module, bytes32 indexed _moduleName, address indexed _moduleFactory, address _creator, uint256 _setupCost, + uint256 _setupCostInPoly, uint256 _timestamp ); event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); @@ -44,19 +44,13 @@ interface IModuleFactory { * @notice Used to change the setup fee * @param _newSetupCost New setup fee */ - function changeFactorySetupFee(uint256 _newSetupCost) external; + function changeSetupCost(uint256 _newSetupCost) external; /** * @notice Used to change the usage fee * @param _newUsageCost New usage fee */ - function changeFactoryUsageFee(uint256 _newUsageCost) external; - - /** - * @notice Used to change the subscription fee - * @param _newSubscriptionCost New subscription fee - */ - function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) external; + function changeUsageCost(uint256 _newUsageCost) external; /** * @notice Function use to change the lower and upper bound of the compatible version st @@ -66,10 +60,15 @@ interface IModuleFactory { function changeSTVersionBounds(string calldata _boundType, uint8[] calldata _newVersion) external; /** - * @notice Get the setup cost of the module + * @notice Get the setup cost of the module in USD */ function getSetupCost() external view returns(uint256); + /** + * @notice Get the setup cost of the module + */ + function getSetupCostInPoly() external view returns (uint256); + /** * @notice Used to get the lower bound * @return Lower bound diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index 720c480f7..edb84d26d 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -8,19 +8,20 @@ import "../modules/Experimental/Burn/TrackedRedemptionFactory.sol"; */ contract MockBurnFactory is TrackedRedemptionFactory { + /** * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module + * @param _polymathRegistry Address of the Polymath Registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost - ) - public - TrackedRedemptionFactory(_setupCost, _usageCost, _subscriptionCost) + address _polymathRegistry + ) + public + TrackedRedemptionFactory(_setupCost, _usageCost, _polymathRegistry) { } @@ -31,15 +32,15 @@ contract MockBurnFactory is TrackedRedemptionFactory { */ function deploy( bytes calldata /*_data*/ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); //Check valid bytes - can only call module init function MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(mockRedemptionManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(mockRedemptionManager), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return address(mockRedemptionManager); } diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 558323584..a9a8d5695 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -13,17 +13,17 @@ contract MockFactory is DummySTOFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath Registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) + address _logicContract, + address _polymathRegistry + ) + public + DummySTOFactory(_setupCost, _usageCost, _logicContract, _polymathRegistry) { } diff --git a/contracts/mocks/MockWrongTypeFactory.sol b/contracts/mocks/MockWrongTypeFactory.sol index a5d2b74ec..27f256023 100644 --- a/contracts/mocks/MockWrongTypeFactory.sol +++ b/contracts/mocks/MockWrongTypeFactory.sol @@ -13,15 +13,15 @@ contract MockWrongTypeFactory is MockBurnFactory { * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module + * @param _polymathRegistry Address of the Polymath Registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost - ) - public - MockBurnFactory(_setupCost, _usageCost, _subscriptionCost) + address _polymathRegistry + ) + public + MockBurnFactory(_setupCost, _usageCost, _polymathRegistry) { } diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index 47c7cd280..2117f3796 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -7,17 +7,17 @@ contract TestSTOFactory is DummySTOFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath Registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - DummySTOFactory(_setupCost, _usageCost, _subscriptionCost, _logicContract) + address _logicContract, + address _polymathRegistry + ) + public + DummySTOFactory(_setupCost, _usageCost, _logicContract, _polymathRegistry) { version = "1.0.0"; name = "TestSTO"; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 041c8222a..3410e2f36 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -15,17 +15,17 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract + address _logicContract, + address _polymathRegistry ) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -51,7 +51,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { (success, ) = erc20DividendCheckpoint.call(_data); require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return erc20DividendCheckpoint; } diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 9802af2ee..38f1b16b4 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -15,17 +15,17 @@ contract EtherDividendCheckpointFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract + address _logicContract, + address _polymathRegistry ) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -51,7 +51,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { (success, ) = ethDividendCheckpoint.call(_data); require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return ethDividendCheckpoint; } diff --git a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol index 729bfe854..603d65600 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemptionFactory.sol @@ -11,15 +11,15 @@ contract TrackedRedemptionFactory is ModuleFactory { * @notice Constructor * @param _setupCost Setup cost of module * @param _usageCost Usage cost of module - * @param _subscriptionCost Monthly cost of module + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "1.0.0"; name = "TrackedRedemption"; @@ -35,15 +35,15 @@ contract TrackedRedemptionFactory is ModuleFactory { */ function deploy( bytes calldata /* _data */ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); address trackedRedemption = address(new TrackedRedemption(msg.sender, polyToken)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(trackedRedemption), getName(), address(this), msg.sender, setupCost, now); - return address(trackedRedemption); + emit GenerateModuleFromFactory(trackedRedemption, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); + return trackedRedemption; } /** diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol index e2b9e57c4..86f4687a7 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpointFactory.sol @@ -11,15 +11,15 @@ contract ScheduledCheckpointFactory is ModuleFactory { * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "1.0.0"; name = "ScheduledCheckpoint"; @@ -35,13 +35,13 @@ contract ScheduledCheckpointFactory is ModuleFactory { */ function deploy( bytes calldata /* _data */ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); address scheduledCheckpoint = address(new ScheduledCheckpoint(msg.sender, polyToken)); - emit GenerateModuleFromFactory(scheduledCheckpoint, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(scheduledCheckpoint, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return scheduledCheckpoint; } @@ -55,41 +55,6 @@ contract ScheduledCheckpointFactory 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 memory) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string memory) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string memory) { - 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 */ diff --git a/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol index d193864b9..2c01246ff 100644 --- a/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/BlacklistTransferManagerFactory.sol @@ -13,10 +13,10 @@ contract BlacklistTransferManagerFactory is ModuleFactory { * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module + * @param _polymathRegistry Address of the Polymath registry */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, address _polymathRegistry) public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "2.1.0"; name = "BlacklistTransferManager"; @@ -34,7 +34,7 @@ contract BlacklistTransferManagerFactory is ModuleFactory { address polyToken = _takeFee(); address blacklistTransferManager = address(new BlacklistTransferManager(msg.sender, address(polyToken))); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(blacklistTransferManager, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(blacklistTransferManager, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return blacklistTransferManager; } diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol index 8a5d8f23c..f8de5dbef 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManagerFactory.sol @@ -9,8 +9,8 @@ contract KYCTransferManagerFactory is ModuleFactory { /** * @notice Constructor */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, address _polymathRegistry) public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "1.0.0"; name = "KYCTransferManager"; @@ -27,10 +27,10 @@ contract KYCTransferManagerFactory is ModuleFactory { */ function deploy(bytes calldata /* _data */) external returns(address) { address polyToken = _takeFee(); - KYCTransferManager kycTransferManager = new KYCTransferManager(msg.sender, polyToken); + address kycTransferManager = address(new KYCTransferManager(msg.sender, polyToken)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(kycTransferManager), getName(), address(this), msg.sender, setupCost, now); - return address(kycTransferManager); + emit GenerateModuleFromFactory(kycTransferManager, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); + return kycTransferManager; } diff --git a/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol index 846133da6..6b47972f1 100644 --- a/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManagerFactory.sol @@ -12,15 +12,15 @@ contract LockUpTransferManagerFactory is ModuleFactory { * @notice Constructor * @param _setupCost Setup cost of the module * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost + address _polymathRegistry ) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "1.0.0"; name = "LockUpTransferManager"; @@ -43,7 +43,7 @@ contract LockUpTransferManagerFactory is ModuleFactory { address polyToken = _takeFee(); LockUpTransferManager lockUpTransferManager = new LockUpTransferManager(msg.sender, polyToken); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(lockUpTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(lockUpTransferManager), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return address(lockUpTransferManager); } diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol index bf23eedf8..8f3f90ced 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol @@ -11,8 +11,8 @@ contract SignedTransferManagerFactory is ModuleFactory { /** * @notice Constructor */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, address _polymathRegistry) public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "1.0.0"; name = "SignedTransferManager"; @@ -38,7 +38,7 @@ contract SignedTransferManagerFactory is ModuleFactory { function deploy(bytes calldata /* _data */) external returns(address) { address polyToken = _takeFee(); SignedTransferManager signedTransferManager = new SignedTransferManager(msg.sender, polyToken); - emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return address(signedTransferManager); } @@ -53,41 +53,6 @@ contract SignedTransferManagerFactory 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 memory) { - return description; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string memory) { - return version; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string memory) { - return title; - } - - /** - * @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 */ diff --git a/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol index 0ddf7123d..da0be5eb5 100644 --- a/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWalletFactory.sol @@ -14,8 +14,8 @@ contract VestingEscrowWalletFactory is ModuleFactory { /** * @notice Constructor */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, address _logicContract, address _polymathRegistry) public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -42,7 +42,7 @@ contract VestingEscrowWalletFactory is ModuleFactory { (success, ) = vestingEscrowWallet.call(_data); require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(vestingEscrowWallet, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(vestingEscrowWallet, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return vestingEscrowWallet; } diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index 28abaa38a..bc053e355 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -3,23 +3,28 @@ pragma solidity ^0.5.0; import "../RegistryUpdater.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IModuleFactory.sol"; +import "../interfaces/IOracle.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "../libraries/VersionUtils.sol"; +import "../interfaces/IPolymathRegistry.sol"; +import "../libraries/DecimalMath.sol"; /** * @title Interface that any module factory contract should implement * @notice Contract is abstract */ contract ModuleFactory is IModuleFactory, Ownable { - uint256 public usageCost; - uint256 public monthlySubscriptionCost; - + // Fee to create underlying module in USD uint256 public setupCost; + uint256 public usageCost; + address public polymathRegistry; string public description; string public version; bytes32 public name; string public title; + string constant POLY_ORACLE = "PolyUsdOracle"; + // @notice Allow only two variables to be stored // 1. lowerBound // 2. upperBound @@ -30,40 +35,30 @@ contract ModuleFactory is IModuleFactory, Ownable { /** * @notice Constructor */ - constructor(uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public { + constructor(uint256 _setupCost, uint256 _usageCost, address _polymathRegistry) public { setupCost = _setupCost; usageCost = _usageCost; - monthlySubscriptionCost = _subscriptionCost; + polymathRegistry = _polymathRegistry; } /** * @notice Used to change the fee of the setup cost - * @param _newSetupCost new setup cost + * @param _newSetupCost new setup cost in USD */ - function changeFactorySetupFee(uint256 _newSetupCost) public onlyOwner { - emit ChangeFactorySetupFee(setupCost, _newSetupCost, address(this)); + function changeSetupCost(uint256 _newSetupCost) public onlyOwner { + emit ChangeSetupCost(setupCost, _newSetupCost); setupCost = _newSetupCost; } /** * @notice Used to change the fee of the usage cost - * @param _newUsageCost new usage cost + * @param _newUsageCost new usage cost in USD */ - function changeFactoryUsageFee(uint256 _newUsageCost) public onlyOwner { - emit ChangeFactoryUsageFee(usageCost, _newUsageCost, address(this)); + function changeUsageCost(uint256 _newUsageCost) public onlyOwner { + emit ChangeUsageCost(usageCost, _newUsageCost); usageCost = _newUsageCost; } - /** - * @notice Used to change the fee of the subscription cost - * @param _newSubscriptionCost new subscription cost - */ - function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) public onlyOwner { - emit ChangeFactorySubscriptionFee(monthlySubscriptionCost, _newSubscriptionCost, address(this)); - monthlySubscriptionCost = _newSubscriptionCost; - - } - /** * @notice Updates the title of the ModuleFactory * @param _newTitle New Title that will replace the old one. @@ -140,22 +135,34 @@ contract ModuleFactory is IModuleFactory, Ownable { /** * @notice Get the setup cost of the module */ - function getSetupCost() external view returns(uint256) { + function getSetupCost() public view returns (uint256) { return setupCost; } /** - * @notice Get the name of the Module - */ + * @notice Get the setup cost of the module + */ + function getSetupCostInPoly() public view returns (uint256) { + uint256 polyRate = IOracle(IPolymathRegistry(polymathRegistry).getAddress(POLY_ORACLE)).getPrice(); + return DecimalMath.div(setupCost, polyRate); + } + + /** + * @notice Get the name of the Module + */ function getName() public view returns(bytes32) { return name; } + + /** + * @notice Calculates fee in POLY + */ function _takeFee() internal returns(address) { - address polyToken = RegistryUpdater(msg.sender).polyToken(); - require(polyToken != address(0), "Invalid POLY token"); - if (setupCost > 0) { - require(IERC20(polyToken).transferFrom(msg.sender, owner(), setupCost), "Insufficient allowance for module fee"); + uint256 setupCostInPoly = getSetupCostInPoly(); + address polyToken = IPolymathRegistry(polymathRegistry).getAddress("PolyToken"); + if (setupCostInPoly > 0) { + require(IERC20(polyToken).transferFrom(msg.sender, owner(), setupCostInPoly), "Insufficient allowance for module fee"); } return polyToken; } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index f1b52dd9f..646c739c8 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -14,17 +14,17 @@ contract GeneralPermissionManagerFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -42,14 +42,14 @@ contract GeneralPermissionManagerFactory is ModuleFactory { */ function deploy( bytes calldata /* _data */ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); address permissionManager = address(new GeneralPermissionManagerProxy(msg.sender, polyToken, logicContract)); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(permissionManager, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return permissionManager; } diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index abb32f9d5..1f6a63311 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -16,17 +16,17 @@ contract CappedSTOFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "2.1.0"; @@ -54,8 +54,8 @@ contract CappedSTOFactory is ModuleFactory { (success, ) = cappedSTO.call(_data); require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(cappedSTO, getName(), address(this), msg.sender, setupCost, now); - return cappedSTO; + emit GenerateModuleFromFactory(address(cappedSTO), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); + return address(cappedSTO); } /** diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index ee84a4251..57cd7eea6 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -16,17 +16,17 @@ contract DummySTOFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { version = "1.0.0"; name = "DummySTO"; @@ -53,7 +53,7 @@ contract DummySTOFactory is ModuleFactory { (success, ) = dummySTO.call(_data); require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(dummySTO, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(dummySTO, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return dummySTO; } diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index e3ae055d1..cfa617faa 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -16,17 +16,17 @@ contract PreSaleSTOFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -54,7 +54,7 @@ contract PreSaleSTOFactory is ModuleFactory { (success, ) = preSaleSTO.call(_data); require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(preSaleSTO, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(preSaleSTO, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return preSaleSTO; } diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index e691bce09..cec5420c0 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -15,16 +15,17 @@ contract USDTieredSTOFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract + address _logicContract, + address _polymathRegistry ) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "0x address is not allowed"); logicContract = _logicContract; @@ -51,7 +52,7 @@ contract USDTieredSTOFactory is ModuleFactory { (success, ) = usdTieredSTO.call(_data); require(success, "Unsuccessfull call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return usdTieredSTO; } diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index f045fabc5..06873ac5a 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -16,16 +16,16 @@ contract CountTransferManagerFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "2.1.0"; @@ -51,9 +51,8 @@ contract CountTransferManagerFactory is ModuleFactory { (success, ) = countTransferManager.call(_data); require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(countTransferManager, getName(), address(this), msg.sender, setupCost, now); - return countTransferManager; - + emit GenerateModuleFromFactory(address(countTransferManager), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); + return address(countTransferManager); } /** diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4c6d4a130..5718ffbbc 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -13,17 +13,17 @@ contract GeneralTransferManagerFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid logic contract"); version = "2.1.0"; @@ -41,14 +41,14 @@ contract GeneralTransferManagerFactory is ModuleFactory { */ function deploy( bytes calldata /* _data */ - ) - external - returns(address) + ) + external + returns(address) { address polyToken = _takeFee(); GeneralTransferManagerProxy generalTransferManager = new GeneralTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return address(generalTransferManager); } diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 6d50e9e2f..9a1f2e7df 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -14,17 +14,17 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract + address _logicContract, + address _polymathRegistry ) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "2.1.0"; @@ -49,7 +49,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { address polyToken = _takeFee(); ManualApprovalTransferManagerProxy manualTransferManager = new ManualApprovalTransferManagerProxy(msg.sender, polyToken, logicContract); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return address(manualTransferManager); } diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 4bed16c4d..3154022e3 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -16,17 +16,17 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @notice Constructor * @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` + * @param _polymathRegistry Address of the Polymath registry */ constructor( uint256 _setupCost, uint256 _usageCost, - uint256 _subscriptionCost, - address _logicContract - ) - public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + address _logicContract, + address _polymathRegistry + ) + public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -52,9 +52,8 @@ contract PercentageTransferManagerFactory is ModuleFactory { (success, ) = percentageTransferManager.call(_data); require(success, "Unsuccessful call"); /*solium-disable-next-line security/no-block-members*/ - emit GenerateModuleFromFactory(percentageTransferManager, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(percentageTransferManager, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return percentageTransferManager; - } /** diff --git a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol index b105dba6f..77ed2c7bd 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTMFactory.sol @@ -12,9 +12,13 @@ contract VolumeRestrictionTMFactory is ModuleFactory { /** * @notice Constructor + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _logicContract Contract address that contains the logic related to `description` + * @param _polymathRegistry Address of the Polymath registry */ - constructor (uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _logicContract) public - ModuleFactory(_setupCost, _usageCost, _subscriptionCost) + constructor (uint256 _setupCost, uint256 _usageCost, address _logicContract, address _polymathRegistry) public + ModuleFactory(_setupCost, _usageCost, _polymathRegistry) { require(_logicContract != address(0), "Invalid address"); version = "1.0.0"; @@ -35,7 +39,7 @@ contract VolumeRestrictionTMFactory is ModuleFactory { address polyToken = _takeFee(); address volumeRestrictionTransferManager = address(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); + emit GenerateModuleFromFactory(volumeRestrictionTransferManager, getName(), address(this), msg.sender, getSetupCost(), getSetupCostInPoly(), now); return volumeRestrictionTransferManager; } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 381209b7a..1bb6c9534 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -235,7 +235,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater IModuleRegistry(moduleRegistry).useModule(_moduleFactory); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); uint8[] memory moduleTypes = moduleFactory.getTypes(); - uint256 moduleCost = moduleFactory.getSetupCost(); + uint256 moduleCost = moduleFactory.getSetupCostInPoly(); require(moduleCost <= _maxCost, "Invalid cost"); //Approve fee for module ERC20(polyToken).approve(_moduleFactory, moduleCost); diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index d6bd8efcd..dae22700d 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -270,54 +270,54 @@ module.exports = function(deployer, network, accounts) { .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, new BN(0), new BN(0), new BN(0), GeneralTransferManagerLogic.address, { + return deployer.deploy(GeneralTransferManagerFactory, new BN(0), new BN(0), GeneralTransferManagerLogic.address, polymathRegistry.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) - return deployer.deploy(GeneralPermissionManagerFactory, new BN(0), new BN(0), new BN(0), GeneralPermissionManagerLogic.address, { + return deployer.deploy(GeneralPermissionManagerFactory, new BN(0), new BN(0), GeneralPermissionManagerLogic.address, polymathRegistry.address, { from: PolymathAccount }); }) .then(() => { // 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, new BN(0), new BN(0), new BN(0), CountTransferManagerLogic.address, { + return deployer.deploy(CountTransferManagerFactory, new BN(0), new BN(0), CountTransferManagerLogic.address, polymathRegistry.address, { 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) - return deployer.deploy(PercentageTransferManagerFactory, new BN(0), new BN(0), new BN(0), PercentageTransferManagerLogic.address, { + return deployer.deploy(PercentageTransferManagerFactory, new BN(0), new BN(0), PercentageTransferManagerLogic.address, polymathRegistry.address, { 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) - return deployer.deploy(EtherDividendCheckpointFactory, new BN(0), new BN(0), new BN(0), EtherDividendCheckpointLogic.address, { + return deployer.deploy(EtherDividendCheckpointFactory, new BN(0), new BN(0), EtherDividendCheckpointLogic.address, polymathRegistry.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, new BN(0), new BN(0), new BN(0), ERC20DividendCheckpointLogic.address, { + return deployer.deploy(ERC20DividendCheckpointFactory, new BN(0), new BN(0), ERC20DividendCheckpointLogic.address, polymathRegistry.address, { 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, new BN(0), new BN(0), new BN(0), VolumeRestrictionTMLogic.address, { from: PolymathAccount }); + return deployer.deploy(VolumeRestrictionTMFactory, new BN(0), new BN(0), VolumeRestrictionTMLogic.address, polymathRegistry.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) - return deployer.deploy(ManualApprovalTransferManagerFactory, new BN(0), new BN(0), new BN(0), ManualApprovalTransferManagerLogic.address, { + return deployer.deploy(ManualApprovalTransferManagerFactory, new BN(0), new BN(0), ManualApprovalTransferManagerLogic.address, polymathRegistry.address, { from: PolymathAccount }); }) @@ -457,7 +457,7 @@ module.exports = function(deployer, network, accounts) { }) .then(() => { // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). - return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, new BN(0), new BN(0), CappedSTOLogic.address, { from: PolymathAccount }); + return deployer.deploy(CappedSTOFactory, cappedSTOSetupCost, new BN(0), CappedSTOLogic.address, polymathRegistry.address, { from: PolymathAccount }); }) .then(() => { // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. @@ -472,7 +472,7 @@ module.exports = function(deployer, network, accounts) { }) .then(() => { // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). - return deployer.deploy(USDTieredSTOFactory, usdTieredSTOSetupCost, new BN(0), new BN(0), USDTieredSTOLogic.address, { from: PolymathAccount }); + return deployer.deploy(USDTieredSTOFactory, usdTieredSTOSetupCost, new BN(0), USDTieredSTOLogic.address, polymathRegistry.address, { from: PolymathAccount }); }) .then(() => { // I) Register the USDTieredSTOFactory in the ModuleRegistry to make the factory available at the protocol level. diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d98271c7e..f0b7cb24d 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -80,7 +80,7 @@ contract("CappedSTO", async (accounts) => { const budget = 0; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // Capped STO details let startTime_ETH1; @@ -101,7 +101,8 @@ contract("CappedSTO", async (accounts) => { const P_fundRaiseType = 1; const P_rate = new BN(web3.utils.toWei("5")); const cappedSTOSetupCost = new BN(web3.utils.toWei("20000", "ether")); - const maxCost = cappedSTOSetupCost; + const cappedSTOSetupCostPOLY = new BN(web3.utils.toWei("80000", "ether")); + const maxCost = cappedSTOSetupCostPOLY; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; let currentTime; @@ -193,7 +194,7 @@ contract("CappedSTO", async (accounts) => { it("Should fail to launch the STO due to security token doesn't have the sufficient POLY", async () => { let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, new BN(0), [E_fundRaiseType], account_fundsReceiver]); @@ -203,7 +204,7 @@ contract("CappedSTO", async (accounts) => { it("Should fail to launch the STO due to rate is 0", async () => { let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner }); + await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCostPOLY, { from: token_owner }); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, new BN(0), [E_fundRaiseType], account_fundsReceiver]); @@ -497,8 +498,8 @@ contract("CappedSTO", async (accounts) => { startTime_ETH2 = await 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 }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); + await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCostPOLY, { from: token_owner }); let bytesSTO = encodeModuleCall(STOParameters, [ startTime_ETH2, endTime_ETH2, @@ -574,9 +575,10 @@ contract("CappedSTO", async (accounts) => { const MAX_MODULES = 10; let startTime = await latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - - await I_PolyToken.getTokens(new BN(cappedSTOSetupCost.mul(new BN(19))), token_owner); - await I_PolyToken.transfer(I_SecurityToken_ETH.address, new BN(cappedSTOSetupCost.mul(new BN(19))), { from: token_owner }); + for (var i = 0; i < MAX_MODULES; i++) { + await I_PolyToken.getTokens(new BN(cappedSTOSetupCostPOLY), token_owner); + }; + await I_PolyToken.transfer(I_SecurityToken_ETH.address, new BN(cappedSTOSetupCostPOLY.mul(new BN(MAX_MODULES))), { from: token_owner }); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { @@ -639,8 +641,8 @@ contract("CappedSTO", async (accounts) => { startTime_POLY1 = await 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 }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); + await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCostPOLY, { from: token_owner }); let bytesSTO = encodeModuleCall(STOParameters, [ startTime_POLY1, @@ -715,6 +717,7 @@ contract("CappedSTO", async (accounts) => { (await I_SecurityToken_POLY.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 5000 ); + }); it("Verification of the event Token Purchase", async () => { @@ -821,6 +824,7 @@ contract("CappedSTO", async (accounts) => { describe("Test cases for the CappedSTOFactory", async () => { it("should get the exact details of the factory", async () => { assert.equal((await I_CappedSTOFactory.getSetupCost.call()).toString(), cappedSTOSetupCost.toString()); + assert.equal((await I_CappedSTOFactory.getSetupCostInPoly.call()).toString(), cappedSTOSetupCostPOLY.toString()); 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( @@ -918,8 +922,8 @@ contract("CappedSTO", async (accounts) => { startTime_POLY2 = await 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 }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); + await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCostPOLY, { from: token_owner }); let bytesSTO = encodeModuleCall(STOParameters, [ startTime_POLY2, diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index d50620db6..f115d9c1c 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -59,7 +59,7 @@ contract("Checkpoints", async function(accounts) { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); before(async () => { fromTime = await latestTime(); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index d6de7c581..a742f8990 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -65,7 +65,7 @@ contract("CountTransferManager", async (accounts) => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // CountTransferManager details const holderCount = 2; // Maximum number of token holders @@ -156,9 +156,9 @@ contract("CountTransferManager", async (accounts) => { }); it("Should successfully attach the CountTransferManager factory with the security token", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -166,11 +166,11 @@ contract("CountTransferManager", async (accounts) => { it("Should successfully attach the CountTransferManager factory with the security token", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_CountTransferManagerFactory.address, bytesSTO, - new BN(web3.utils.toWei("500", "ether")), + new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner } ); @@ -434,9 +434,9 @@ contract("CountTransferManager", async (accounts) => { }); it("Should successfully attach the CountTransferManager factory with the security token", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); await catchRevert( - I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -496,37 +496,26 @@ contract("CountTransferManager", async (accounts) => { describe("Test cases for the ModuleFactory", async () => { it("Should successfully change the SetupCost -- fail beacuse of bad owner", async () => { await catchRevert( - I_CountTransferManagerFactory.changeFactorySetupFee(new BN(web3.utils.toWei("500")), { from: account_investor3 }) + I_CountTransferManagerFactory.changeSetupCost(new BN(web3.utils.toWei("500")), { from: account_investor3 }) ); }); it("Should successfully change the setupCost", async () => { - await I_CountTransferManagerFactory.changeFactorySetupFee(new BN(web3.utils.toWei("800")), { from: account_polymath }); + await I_CountTransferManagerFactory.changeSetupCost(new BN(web3.utils.toWei("800")), { from: account_polymath }); assert.equal((await I_CountTransferManagerFactory.getSetupCost.call()).toString(), new BN(web3.utils.toWei("800")).toString()); }); it("Should successfully change the usage fee -- fail beacuse of bad owner", async () => { await catchRevert( - I_CountTransferManagerFactory.changeFactoryUsageFee(new BN(web3.utils.toWei("500")), { from: account_investor3 }) + I_CountTransferManagerFactory.changeUsageCost(new BN(web3.utils.toWei("500")), { from: account_investor3 }) ); }); it("Should successfully change the usage fee", async () => { - await I_CountTransferManagerFactory.changeFactoryUsageFee(new BN(web3.utils.toWei("800")), { from: account_polymath }); + await I_CountTransferManagerFactory.changeUsageCost(new BN(web3.utils.toWei("800")), { from: account_polymath }); assert.equal((await I_CountTransferManagerFactory.usageCost.call()).toString(), new BN(web3.utils.toWei("800")).toString()); }); - it("Should successfully change the subscription fee -- fail beacuse of bad owner", async () => { - await catchRevert( - I_CountTransferManagerFactory.changeFactorySubscriptionFee(new BN(web3.utils.toWei("500")), { from: account_investor3 }) - ); - }); - - it("Should successfully change the subscription fee", async () => { - await I_CountTransferManagerFactory.changeFactorySubscriptionFee(new BN(web3.utils.toWei("800")), { from: account_polymath }); - assert.equal((await I_CountTransferManagerFactory.monthlySubscriptionCost.call()), new BN(web3.utils.toWei("800")).toString()); - }); - it("Should successfully change the version of the factory -- failed because of bad owner", async () => { await catchRevert(I_CountTransferManagerFactory.changeVersion("5.0.0", { from: account_investor3 })); }); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index f17bd200a..cc1f8f891 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -70,7 +70,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { const managerDetails = web3.utils.fromAscii("Hello"); // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); const one_address = "0x0000000000000000000000000000000000000001"; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -168,7 +168,7 @@ contract("ERC20DividendCheckpoint", async (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, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -176,10 +176,10 @@ contract("ERC20DividendCheckpoint", async (accounts) => { it("Should successfully attach the ERC20DividendCheckpoint with the security token with budget", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); - await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), { from: token_owner }); let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); - const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index dae87c572..a6ace6440 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -71,7 +71,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { const DividendParameters = ["address"]; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let currentTime; @@ -160,10 +160,10 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); await catchRevert( - I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -171,9 +171,9 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), { from: token_owner }); let bytesDividend = encodeModuleCall(DividendParameters, [wallet]); - const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, bytesDividend, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index 6792d6d17..b339376f2 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -66,7 +66,7 @@ contract("GeneralPermissionManager", async (accounts) => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let currentTime; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -136,7 +136,7 @@ contract("GeneralPermissionManager", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -158,9 +158,9 @@ contract("GeneralPermissionManager", async (accounts) => { 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(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -168,11 +168,11 @@ contract("GeneralPermissionManager", async (accounts) => { 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, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_GeneralPermissionManagerFactory.address, "0x", - new BN(web3.utils.toWei("500", "ether")), + new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner } ); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 03c22b23f..3feae6422 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -72,7 +72,7 @@ contract("GeneralTransferManager", async (accounts) => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // Dummy STO details let startTime; @@ -189,14 +189,14 @@ contract("GeneralTransferManager", async (accounts) => { it("Should attach the paid GTM -- failed because of no tokens", async () => { await catchRevert( - I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "0x0", new BN(web3.utils.toWei("500")), new BN(0), { from: account_issuer }) + I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "0x0", new BN(web3.utils.toWei("2000")), new BN(0), { from: account_issuer }) ); }); it("Should attach the paid GTM", async () => { let snap_id = await takeSnapshot(); - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); - await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "0x0", new BN(web3.utils.toWei("500")), new BN(0), { + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000")), I_SecurityToken.address); + await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "0x0", new BN(web3.utils.toWei("2000")), new BN(0), { from: account_issuer }); await revertToSnapshot(snap_id); @@ -257,7 +257,7 @@ contract("GeneralTransferManager", async (accounts) => { someString ]); await catchRevert( - I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { from: token_owner }) + I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("2000")), new BN(0), { from: token_owner }) ); }); @@ -269,8 +269,8 @@ contract("GeneralTransferManager", async (accounts) => { cap, someString ]); - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000")), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, new BN(web3.utils.toWei("2000")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); @@ -306,7 +306,7 @@ contract("GeneralTransferManager", async (accounts) => { }); it("Should successfully attach the permission manager factory with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, new BN(0), new BN(0), new BN(0), { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(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, ""), diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index f9d0ab10c..1c3a0fe6b 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -1,6 +1,7 @@ import { encodeProxyCall, encodeModuleCall } from "./encodeCall"; const PolymathRegistry = artifacts.require("./PolymathRegistry.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"); @@ -100,6 +101,8 @@ let I_STRProxied; let I_MRProxied; let I_STRGetter; let I_SignedTransferManagerFactory; +let I_USDOracle; +let I_POLYOracle; // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); @@ -129,6 +132,9 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { await setInPolymathRegistry(account_polymath); // STEP 9: Register the Modules with the ModuleRegistry contract await registerGTM(account_polymath); + // STEP 10: Add dummy oracles + await addOracles(account_polymath); + let tempArray = new Array( I_PolymathRegistry, I_PolyToken, @@ -146,6 +152,15 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { return Promise.all(tempArray); } +export async function addOracles(account_polymath) { + let USDETH = new BN(500).mul(new BN(10).pow(new BN(18))); // 500 USD/ETH + let USDPOLY = new BN(25).mul(new BN(10).pow(new BN(16))); // 0.25 USD/POLY + I_USDOracle = await MockOracle.new("0x0000000000000000000000000000000000000000", web3.utils.fromAscii("ETH"), web3.utils.fromAscii("USD"), USDETH, { from: account_polymath }); // 500 dollars per POLY + I_POLYOracle = await MockOracle.new(I_PolyToken.address, web3.utils.fromAscii("POLY"), web3.utils.fromAscii("USD"), USDPOLY, { from: account_polymath }); // 25 cents per POLY + await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: account_polymath }); + await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: account_polymath }); +} + export async function deployPolyRegistryAndPolyToken(account_polymath, token_owner) { // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({ from: account_polymath }); @@ -195,7 +210,7 @@ async function deployGTMLogic(account_polymath) { } async function deployGTM(account_polymath) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(new BN(0), new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, I_PolymathRegistry.address, { from: account_polymath }); @@ -266,7 +281,7 @@ async function registerAndVerifyByMR(factoryAdrress, owner, mr) { /// Deploy the TransferManagers export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(setupCost, new BN(0), I_GeneralTransferManagerLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); @@ -284,7 +299,7 @@ export async function deployGTMAndVerifyed(accountPolymath, MRProxyInstance, set export async function deployVRTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_VolumeRestrictionTMLogic = await VolumeRestrictionTM.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_VolumeRestrictionTMFactory = await VolumeRestrictionTMFactory.new(setupCost, new BN(0), new BN(0), I_VolumeRestrictionTMLogic.address, { from: accountPolymath }); + I_VolumeRestrictionTMFactory = await VolumeRestrictionTMFactory.new(setupCost, new BN(0), I_VolumeRestrictionTMLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_VolumeRestrictionTMFactory.address.valueOf(), @@ -299,7 +314,7 @@ export async function deployVRTMAndVerifyed(accountPolymath, MRProxyInstance, se export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_CountTransferManagerLogic = await CountTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_CountTransferManagerLogic.address, { from: accountPolymath }); + I_CountTransferManagerFactory = await CountTransferManagerFactory.new(setupCost, new BN(0), I_CountTransferManagerLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_CountTransferManagerFactory.address.valueOf(), @@ -313,7 +328,7 @@ export async function deployCountTMAndVerifyed(accountPolymath, MRProxyInstance, export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_ManualApprovalTransferManagerLogic = await ManualApprovalTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, new BN(0), new BN(0), ManualApprovalTransferManager.address, { from: accountPolymath }); + I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(setupCost, new BN(0), ManualApprovalTransferManager.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_ManualApprovalTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -326,7 +341,7 @@ export async function deployManualApprovalTMAndVerifyed(accountPolymath, MRProxy export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { I_PercentageTransferManagerLogic = await PercentageTransferManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, new BN(0), new BN(0), I_PercentageTransferManagerLogic.address, { from: accountPolymath }); + I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(setupCost, new BN(0), I_PercentageTransferManagerLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_PercentageTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -339,7 +354,7 @@ export async function deployPercentageTMAndVerified(accountPolymath, MRProxyInst export async function deployBlacklistTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); + I_BlacklistTransferManagerFactory = await BlacklistTransferManagerFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_BlacklistTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -351,7 +366,7 @@ export async function deployBlacklistTMAndVerified(accountPolymath, MRProxyInsta } export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_VolumeRestrictionTransferManagerFactory = await LockUpTransferManagerFactory.new(setupCost, new BN(0), new BN(0), { + I_VolumeRestrictionTransferManagerFactory = await LockUpTransferManagerFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( @@ -365,7 +380,7 @@ export async function deployLockupVolumeRTMAndVerified(accountPolymath, MRProxyI } export async function deployScheduleCheckpointAndVerified(accountPolymath, MRProxyInstance, setupCost) { - I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); + I_ScheduledCheckpointFactory = await ScheduledCheckpointFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_ScheduledCheckpointFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -380,7 +395,7 @@ export async function deployScheduleCheckpointAndVerified(accountPolymath, MRPro export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, { from: accountPolymath }); + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(setupCost, new BN(0), I_GeneralPermissionManagerLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_GeneralPermissionManagerFactory.address.valueOf(), @@ -397,7 +412,7 @@ export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, set export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_DummySTOLogic = await DummySTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_DummySTOFactory = await DummySTOFactory.new(setupCost, new BN(0), new BN(0), I_DummySTOLogic.address,{ from: accountPolymath }); + I_DummySTOFactory = await DummySTOFactory.new(setupCost, new BN(0), I_DummySTOLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_DummySTOFactory.address.valueOf(), @@ -410,7 +425,7 @@ export async function deployDummySTOAndVerifyed(accountPolymath, MRProxyInstance export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_CappedSTOLogic = await CappedSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, new BN(0), new BN(0), I_CappedSTOLogic.address, { from: accountPolymath }); + I_CappedSTOFactory = await CappedSTOFactory.new(setupCost, new BN(0), I_CappedSTOLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_CappedSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -423,7 +438,7 @@ export async function deployCappedSTOAndVerifyed(accountPolymath, MRProxyInstanc export async function deployPresaleSTOAndVerified(accountPolymath, MRProxyInstance, setupCost) { I_PreSaleSTOLogic = await PreSaleSTO.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, new BN(0), new BN(0), I_PreSaleSTOLogic.address, { from: accountPolymath }); + I_PreSaleSTOFactory = await PreSaleSTOFactory.new(setupCost, new BN(0), I_PreSaleSTOLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_PreSaleSTOFactory.address.valueOf(), @@ -442,7 +457,7 @@ export async function deployUSDTieredSTOAndVerified(accountPolymath, MRProxyInst { from: accountPolymath } ); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, new BN(0), new BN(0), I_USDTieredSTOLogic.address, { from: accountPolymath }); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(setupCost, new BN(0), I_USDTieredSTOLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), @@ -462,7 +477,7 @@ export async function deployERC20DividendAndVerifyed(accountPolymath, MRProxyIns "0x0000000000000000000000000000000000000000", { from: accountPolymath } ); - I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, new BN(0), new BN(0), I_ERC20DividendCheckpointLogic.address, { + I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(setupCost, new BN(0), I_ERC20DividendCheckpointLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); @@ -481,7 +496,7 @@ export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyIns "0x0000000000000000000000000000000000000000", { from: accountPolymath } ); - I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, new BN(0), new BN(0), I_EtherDividendCheckpointLogic.address, { + I_EtherDividendCheckpointFactory = await EtherDividendCheckpointFactory.new(setupCost, new BN(0), I_EtherDividendCheckpointLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); @@ -498,7 +513,7 @@ export async function deployEtherDividendAndVerifyed(accountPolymath, MRProxyIns /// Deploy the Burn Module export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); + I_TrackedRedemptionFactory = await TrackedRedemptionFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_TrackedRedemptionFactory.address.valueOf(), @@ -512,7 +527,7 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan export async function deployVestingEscrowWalletAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { I_VestingEscrowWalletLogic = await VestingEscrowWallet.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: accountPolymath }); - I_VestingEscrowWalletFactory = await VestingEscrowWalletFactory.new(setupCost, new BN(0), new BN(0), I_VestingEscrowWalletLogic.address, { from: accountPolymath }); + I_VestingEscrowWalletFactory = await VestingEscrowWalletFactory.new(setupCost, new BN(0), I_VestingEscrowWalletLogic.address, I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_VestingEscrowWalletFactory.address.valueOf(), @@ -525,7 +540,7 @@ export async function deployVestingEscrowWalletAndVerifyed(accountPolymath, MRPr } export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_MockBurnFactory = await MockBurnFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); + I_MockBurnFactory = await MockBurnFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_MockBurnFactory.address.valueOf(), @@ -538,7 +553,7 @@ export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyIn } export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, MRProxyInstance, setupCost) { - I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(setupCost, new BN(0), new BN(0), { from: accountPolymath }); + I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_MockWrongTypeBurnFactory.address.valueOf(), @@ -551,7 +566,7 @@ export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, } export async function deploySignedTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { - I_SignedTransferManagerFactory = await SignedTransferManagerFactory.new(setupCost, 0, 0, { from: accountPolymath }); + I_SignedTransferManagerFactory = await SignedTransferManagerFactory.new(setupCost, new BN(0), I_PolymathRegistry.address, { from: accountPolymath }); assert.notEqual( I_SignedTransferManagerFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -560,4 +575,4 @@ export async function deploySignedTMAndVerifyed(accountPolymath, MRProxyInstance await registerAndVerifyByMR(I_SignedTransferManagerFactory.address, accountPolymath, MRProxyInstance); return new Array(I_SignedTransferManagerFactory); -} \ No newline at end of file +} diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 7b62336bd..15f68fc2a 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -68,7 +68,7 @@ contract("Issuance", async (accounts) => { const one_address = "0x0000000000000000000000000000000000000001"; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // Capped STO details //let startTime; // Start time will be 5000 seconds more than the latest time @@ -77,7 +77,8 @@ contract("Issuance", async (accounts) => { const rate = new BN(web3.utils.toWei("1000")); const fundRaiseType = [0]; const cappedSTOSetupCost = new BN(web3.utils.toWei("20000", "ether")); - const maxCost = cappedSTOSetupCost; + const cappedSTOSetupCostPOLY = new BN(web3.utils.toWei("80000", "ether")); + const maxCost = cappedSTOSetupCostPOLY; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; const MRProxyParameters = ["address", "address"]; @@ -149,7 +150,7 @@ contract("Issuance", async (accounts) => { it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_polymath }); - + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_polymath }); // Verify the successful generation of the security token @@ -183,8 +184,8 @@ contract("Issuance", async (accounts) => { account_fundsReceiver ]); - await I_PolyToken.getTokens(cappedSTOSetupCost, account_polymath); - await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: account_polymath }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, account_polymath); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCostPOLY, { from: account_polymath }); const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: account_polymath }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 26580b093..b46239995 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -72,7 +72,7 @@ contract("ManualApprovalTransferManager", accounts => { let approvalTime; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = web3.utils.toWei("1000"); const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; let currentTime; @@ -225,9 +225,9 @@ contract("ManualApprovalTransferManager", accounts => { }); it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await I_PolyToken.getTokens(web3.utils.toWei("2000", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x0", web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x0", web3.utils.toWei("2000", "ether"), 0, { from: token_owner }) ); @@ -235,11 +235,11 @@ contract("ManualApprovalTransferManager", accounts => { 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 }); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("2000", "ether"), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_ManualApprovalTransferManagerFactory.address, "0x0", - web3.utils.toWei("500", "ether"), + web3.utils.toWei("2000", "ether"), 0, { from: token_owner } ); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index efba2e2f2..036949f9a 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -80,7 +80,7 @@ contract("ModuleRegistry", async (accounts) => { const one_address = "0x0000000000000000000000000000000000000001"; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // delagate details const delegateDetails = "I am delegate .."; @@ -253,14 +253,14 @@ contract("ModuleRegistry", async (accounts) => { }); it("Should fail in registering the module-- type = 0", async () => { - I_MockFactory = await MockFactory.new(new BN(0), new BN(0), new BN(0), address_zero, { from: account_polymath }); + I_MockFactory = await MockFactory.new(new BN(0), new BN(0), address_zero, I_PolymathRegistry.address, { from: account_polymath }); catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); }); it("Should fail to register the new module because msg.sender is not the owner of the module", async() => { I_CappedSTOLogic = await CappedSTO.new(address_zero, address_zero, { from: account_polymath }); - I_CappedSTOFactory3 = await CappedSTOFactory.new(new BN(0), new BN(0), new BN(0), I_CappedSTOLogic.address, { from: account_temp }); + I_CappedSTOFactory3 = await CappedSTOFactory.new(new BN(0), new BN(0), I_CappedSTOLogic.address, I_PolymathRegistry.address, { from: account_temp }); catchRevert(I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: token_owner })); }); @@ -282,7 +282,7 @@ contract("ModuleRegistry", async (accounts) => { }); it("Should successfully verify the module -- false", async () => { - I_CappedSTOFactory1 = await CappedSTOFactory.new(new BN(0), new BN(0), new BN(0), I_CappedSTOLogic.address, { from: account_polymath }); + I_CappedSTOFactory1 = await CappedSTOFactory.new(new BN(0), new BN(0), I_CappedSTOLogic.address, I_PolymathRegistry.address, { 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"); @@ -296,8 +296,8 @@ contract("ModuleRegistry", async (accounts) => { describe("Test cases for the useModule function of the module registry", async () => { it("Deploy the securityToken", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), account_issuer); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: account_issuer }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000")), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("2000")), { 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[2].args._ticker, symbol.toUpperCase()); @@ -313,7 +313,7 @@ contract("ModuleRegistry", async (accounts) => { }); it("Should fail to register module because custom modules not allowed", async () => { - I_CappedSTOFactory2 = await CappedSTOFactory.new(0, new BN(0), new BN(0), I_CappedSTOLogic.address, { from: token_owner }); + I_CappedSTOFactory2 = await CappedSTOFactory.new(new BN(0), new BN(0), I_CappedSTOLogic.address, I_PolymathRegistry.address, { from: token_owner }); assert.notEqual(I_CappedSTOFactory2.address.valueOf(), address_zero, "CappedSTOFactory contract was not deployed"); @@ -361,7 +361,7 @@ contract("ModuleRegistry", async (accounts) => { it("Should successfully add verified module", async () => { I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(0, new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, { + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, I_PolymathRegistry.address, { from: account_polymath }); await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); @@ -371,7 +371,7 @@ contract("ModuleRegistry", async (accounts) => { }); it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async () => { - I_TestSTOFactory = await TestSTOFactory.new(new BN(0), new BN(0), new BN(0), address_zero, { from: account_polymath }); + I_TestSTOFactory = await TestSTOFactory.new(new BN(0), new BN(0), address_zero, I_PolymathRegistry.address, { 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 @@ -398,8 +398,8 @@ contract("ModuleRegistry", async (accounts) => { // Generate the new securityToken let newSymbol = "toro"; - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), account_issuer); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: account_issuer }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000")), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("2000")), { 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[2].args._ticker, newSymbol.toUpperCase()); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index b27f34427..428f35b41 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -63,7 +63,7 @@ contract("PercentageTransferManager", async (accounts) => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // PercentageTransferManager details const holderPercentage = 70 * 10 ** 16; // Maximum number of token holders @@ -252,9 +252,9 @@ contract("PercentageTransferManager", async (accounts) => { }); it("Should successfully attach the PercentageTransferManager factory with the security token - failed payment", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -262,11 +262,11 @@ contract("PercentageTransferManager", async (accounts) => { it("Should successfully attach the PercentageTransferManager factory with the security token", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_PercentageTransferManagerFactory.address, bytesSTO, - new BN(web3.utils.toWei("500", "ether")), + new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner } ); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index daa982397..86259560c 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -69,7 +69,7 @@ contract("PreSaleSTO", async (accounts) => { const budget = 0; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let endTime; const address_zero = "0x0000000000000000000000000000000000000000"; const one_address = "0x0000000000000000000000000000000000000001"; diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index d723f4e45..a7d19c13c 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -83,7 +83,7 @@ contract("SecurityTokenRegistry", async (accounts) => { // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); - const newRegFee = new BN(web3.utils.toWei("300")); + const initRegFeePOLY = new BN(web3.utils.toWei("1000")); const STRProxyParameters = ["address", "address", "uint256", "uint256", "address", "address"]; const STOParameters = ["uint256", "uint256", "uint256", "string"]; @@ -324,8 +324,8 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should fail to register ticker if owner is 0x", async () => { - await I_PolyToken.getTokens(initRegFee, account_temp); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp }); + await I_PolyToken.getTokens(initRegFeePOLY, account_temp); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: account_temp }); await catchRevert( I_STRProxied.registerTicker(address_zero, symbol, name, { from: account_temp }), @@ -368,8 +368,8 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should fail to register same symbol again", async () => { // Give POLY to token issuer - await I_PolyToken.getTokens(initRegFee, token_owner); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.getTokens(initRegFeePOLY, token_owner); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); // Call registration function await catchRevert( I_STRProxied.registerTicker(token_owner, symbol, name, { from: token_owner }), @@ -379,7 +379,7 @@ contract("SecurityTokenRegistry", async (accounts) => { 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 }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { 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}`); @@ -387,7 +387,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should fail to register ticker if registration is paused", async () => { await I_STRProxied.pause({ from: account_polymath }); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); await catchRevert( I_STRProxied.registerTicker(token_owner, "AAA", name, { from: token_owner }), @@ -401,7 +401,7 @@ contract("SecurityTokenRegistry", async (accounts) => { 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 }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { 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`); @@ -472,7 +472,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should fail to generate token if registration is paused", async () => { await I_STRProxied.pause({ from: account_polymath }); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); await catchRevert( I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }), @@ -528,7 +528,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should fail to generate the SecurityToken because ticker gets expired", async () => { let snap_Id = await takeSnapshot(); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("2000")), { from: token_owner }); let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); await increaseTime(duration.days(65)); await catchRevert( @@ -541,7 +541,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should generate the SecurityToken when launch fee is 0", async () => { let snap_Id = await takeSnapshot(); await I_STRProxied.changeSecurityLaunchFee(0, { from: account_polymath }); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("2000")), { from: token_owner }); let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); await I_STRProxied.generateSecurityToken(name, "CCC", tokenDetails, false, { from: token_owner }), await revertToSnapshot(snap_Id); @@ -549,8 +549,8 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should get all created security tokens", async() => { let snap_Id = await takeSnapshot(); - await I_PolyToken.getTokens(web3.utils.toWei("500"), account_temp); - await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: account_temp }); + await I_PolyToken.getTokens(web3.utils.toWei("2000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("2000"), { from: account_temp }); await I_STRProxied.registerTicker(account_temp, "TMP", name, { from: account_temp }); let tx = await I_STRProxied.generateSecurityToken(name, "TMP", tokenDetails, false, { from: account_temp }); @@ -593,14 +593,14 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { 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 }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); let tx = await I_STRProxied.generateSecurityToken(name2, symbol2, tokenDetails, false, { from: token_owner }); @@ -705,7 +705,7 @@ contract("SecurityTokenRegistry", async (accounts) => { it("Should successfully generate custom token", async () => { // Register the new ticker -- Fulfiling the TickerStatus.ON condition await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: account_temp }); let tickersListArray = await I_Getter.getTickersByOwner.call(account_temp); console.log(tickersListArray); await I_STRProxied.registerTicker(account_temp, "LOG", "LOGAN", { from: account_temp }); @@ -951,7 +951,7 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should fail to register the ticker with the old fee", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); await catchRevert( I_STRProxied.registerTicker(token_owner, "POLY", "Polymath", { from: token_owner }), "tx revert -> failed because of ticker registeration fee gets change" @@ -959,15 +959,15 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should register the ticker with the new fee", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), token_owner); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: token_owner }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1600")), token_owner); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("2000")), { 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 () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); await catchRevert( I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }), "tx revert -> failed because of old launch fee" @@ -975,7 +975,7 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should launch the the securityToken", async () => { - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("500")), { from: token_owner }); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("2000")), { from: token_owner }); let tx = await I_STRProxied.generateSecurityToken("Polymath", "POLY", tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -1051,8 +1051,8 @@ contract("SecurityTokenRegistry", async (accounts) => { describe(" Test cases of the registerTicker", async () => { it("Should register the ticker 1", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1000")), { from: account_temp }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1600")), account_temp); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1600")), { from: account_temp }); let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "0x0", { 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`); @@ -1060,8 +1060,8 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should register the ticker 2", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1000")), { from: account_temp }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1600")), account_temp); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1600")), { from: account_temp }); let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "0x0", { 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`); @@ -1069,8 +1069,8 @@ contract("SecurityTokenRegistry", async (accounts) => { }); it("Should register the ticker 3", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), account_temp); - await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1000")), { from: account_temp }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("1600")), account_temp); + await I_PolyToken.approve(I_STRProxied.address, new BN(web3.utils.toWei("1600")), { from: account_temp }); let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "0x0", { 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`); diff --git a/test/o_security_token.js b/test/o_security_token.js index d6adbbc99..680950ccd 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -84,7 +84,7 @@ contract("SecurityToken", async (accounts) => { const budget = 0; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // delagate details const delegateDetails = web3.utils.fromAscii("I am delegate .."); @@ -98,7 +98,8 @@ contract("SecurityToken", async (accounts) => { const rate = new BN(web3.utils.toWei("1000")); const fundRaiseType = [0]; const cappedSTOSetupCost = new BN(web3.utils.toWei("20000", "ether")); - const maxCost = cappedSTOSetupCost; + const cappedSTOSetupCostPOLY = new BN(web3.utils.toWei("80000", "ether")); + const maxCost = cappedSTOSetupCostPOLY; const STOParameters = ["uint256", "uint256", "uint256", "uint256", "uint8[]", "address"]; let currentTime; @@ -292,8 +293,8 @@ contract("SecurityToken", async (accounts) => { startTime = await 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 }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCostPOLY, { from: token_owner }); await catchRevert( I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("1000", "ether")), new BN(0), { from: token_owner }) @@ -306,8 +307,8 @@ contract("SecurityToken", async (accounts) => { 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 }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCostPOLY, { from: token_owner }); console.log("0"); const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), web3.utils.fromAscii("stofactory"), { from: token_owner @@ -326,8 +327,8 @@ contract("SecurityToken", async (accounts) => { 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 }); + await I_PolyToken.getTokens(cappedSTOSetupCostPOLY, token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCostPOLY, { from: token_owner }); const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner }); @@ -1047,13 +1048,14 @@ contract("SecurityToken", async (accounts) => { it("Should successfully withdraw the poly", async () => { let balanceBefore = await I_PolyToken.balanceOf(token_owner); - await I_SecurityToken.withdrawERC20(I_PolyToken.address, new BN(web3.utils.toWei("20000", "ether")), { from: token_owner }); + let stBalance = await I_PolyToken.balanceOf(I_SecurityToken.address); + await I_SecurityToken.withdrawERC20(I_PolyToken.address, new BN(stBalance), { from: token_owner }); let balanceAfter = await I_PolyToken.balanceOf(token_owner); assert.equal( BN(balanceAfter) .sub(new BN(balanceBefore)) .toString(), - new BN(web3.utils.toWei("20000", "ether").toString()) + stBalance.toString() ); }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 4661fb043..f70d222ed 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -203,7 +203,7 @@ contract("USDTieredSTO", async (accounts) => { e18 = new BN(10).pow(new BN(18)); e16 = new BN(10).pow(new BN(16)); currentTime = new BN(await latestTime()); - REGFEE = new BN(web3.utils.toWei("250")); + REGFEE = new BN(web3.utils.toWei("1000")); USDETH = new BN(500).mul(new BN(10).pow(new BN(18))); // 500 USD/ETH USDPOLY = new BN(25).mul(new BN(10).pow(new BN(16))); // 0.25 USD/POLY POLYMATH = accounts[0]; @@ -406,7 +406,7 @@ contract("USDTieredSTO", async (accounts) => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); await catchRevert( - I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("2000")), new BN(0), { from: ISSUER, gasPrice: GAS_PRICE }) @@ -432,8 +432,8 @@ contract("USDTieredSTO", async (accounts) => { ]; let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); - let tx = await I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("500")), new BN(0), { + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000")), I_SecurityToken.address); + let tx = await I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, new BN(web3.utils.toWei("2000")), new BN(0), { from: ISSUER, gasPrice: GAS_PRICE }); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index e4f9db8e1..c0f62f589 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -70,7 +70,7 @@ contract("USDTieredSTO Sim", async (accounts) => { const STOKEY = 3; // Initial fee for ticker registry and security token registry - const REGFEE = new BN(web3.utils.toWei("250")); + const REGFEE = new BN(web3.utils.toWei("1000")); const STOSetupCost = 0; // MockOracle USD prices @@ -783,4 +783,4 @@ function assertIsNear(a, b, reason) { } else { assert.isBelow(b.sub(a).toNumber(), 4, reason); } -} \ No newline at end of file +} diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 129116c26..513f8c8a7 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -56,8 +56,9 @@ contract("Concurrent STO", async (accounts) => { let message = "Transaction Should Fail!"; // Initial fees - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); const STOSetupCost = web3.utils.toHex(200 * Math.pow(10, 18)); + const STOSetupCostPOLY = web3.utils.toHex(800 * Math.pow(10, 18)); // Module keys const transferManagerKey = 2; @@ -142,7 +143,7 @@ contract("Concurrent STO", async (accounts) => { 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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_issuer }); assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); @@ -184,7 +185,7 @@ contract("Concurrent STO", async (accounts) => { const rate = new BN(web3.utils.toWei("1000")); const fundRaiseType = [0]; const budget = 0; - const maxCost = STOSetupCost; + const maxCost = STOSetupCostPOLY; const cappedBytesSig = encodeModuleCall(CappedSTOParameters, [ startTime, endTime, @@ -197,8 +198,8 @@ contract("Concurrent STO", async (accounts) => { 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 }); + await I_PolyToken.getTokens(STOSetupCostPOLY, account_issuer); + await I_PolyToken.transfer(I_SecurityToken.address, STOSetupCostPOLY, { from: account_issuer }); switch (STOIndex % 3) { case 0: // Capped STO diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 0854d94e1..d2767dedd 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -39,6 +39,7 @@ contract("SecurityTokenRegistryProxy", async (accounts) => { // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFeePOLY = new BN(web3.utils.toWei("1000")); const version = "1.0.0"; const message = "Transaction Should Fail!"; @@ -147,15 +148,15 @@ contract("SecurityTokenRegistryProxy", async (accounts) => { describe("Feed some data in storage", async () => { it("Register the ticker", async () => { - await I_PolyToken.getTokens(new BN(web3.utils.toWei("1000")), token_owner); - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("8000")), token_owner); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { 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 }); + await I_PolyToken.approve(I_STRProxied.address, initRegFeePOLY, { from: token_owner }); let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 624217939..c4d3c2d98 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -44,7 +44,6 @@ contract("ModuleRegistryProxy", async (accounts) => { let account_polymath_new; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); const version = "1.0.0"; const message = "Transaction Should Fail!"; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -136,7 +135,7 @@ contract("ModuleRegistryProxy", async (accounts) => { { from: account_polymath } ); - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(new BN(0), new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, { + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(new BN(0), new BN(0), I_GeneralTransferManagerLogic.address, I_PolymathRegistry.address, { from: account_polymath }); @@ -173,7 +172,7 @@ contract("ModuleRegistryProxy", async (accounts) => { describe("Feed some data in storage", async () => { it("Register and verify the new module", async () => { I_GeneralPermissionManagerLogic = await GeneralPermissionManager.new("0x0000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000", { from: account_polymath }); - I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(0, new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, { + I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(new BN(0), new BN(0), I_GeneralPermissionManagerLogic.address, I_PolymathRegistry.address, { from: account_polymath }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 28ccaded7..a0b3ba36f 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -63,7 +63,7 @@ contract("TrackedRedemption", async (accounts) => { const burnKey = 5; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let currentTime; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -135,7 +135,7 @@ contract("TrackedRedemption", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token @@ -157,8 +157,8 @@ contract("TrackedRedemption", async (accounts) => { it("Should successfully attach the paid TrackedRedemption with the security token", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.getTokens(new BN(web3.utils.toWei("500")), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(P_TrackedRedemptionFactory.address, "0x0", new BN(web3.utils.toWei("500")), new BN(0), { + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000")), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_TrackedRedemptionFactory.address, "0x0", new BN(web3.utils.toWei("2000")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 0be2bfe04..254ae384f 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -68,7 +68,7 @@ contract('LockUpTransferManager', accounts => { let temp; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let currentTime; before(async() => { @@ -246,17 +246,17 @@ contract('LockUpTransferManager', accounts => { }); 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 I_PolyToken.getTokens(web3.utils.toWei("2000", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), 0, { from: token_owner }) + I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("2000", "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, new BN(web3.utils.toWei("500", "ether")), {from: token_owner}); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), {from: token_owner}); console.log((await P_LockUpTransferManagerFactory.getSetupCost.call()).toString()); - const tx = await I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { from: token_owner }); + const tx = await I_SecurityToken.addModule(P_LockUpTransferManagerFactory.address, "0x", new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toString(), transferManagerKey, "LockUpVolumeRestrictionTMFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) diff --git a/test/x_scheduled_checkpoints.js b/test/x_scheduled_checkpoints.js index aa490f32e..dd23a8f9e 100644 --- a/test/x_scheduled_checkpoints.js +++ b/test/x_scheduled_checkpoints.js @@ -56,7 +56,7 @@ contract("ScheduledCheckpoint", async (accounts) => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let currentTime; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -122,7 +122,7 @@ contract("ScheduledCheckpoint", async (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 tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); // Verify the successful generation of the security token diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 0b5456a0d..e855673dd 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -74,7 +74,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tempArrayGlobal = new Array(); // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); const address_zero = "0x0000000000000000000000000000000000000000"; diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index 54e249a1f..2c4a5cef3 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -67,7 +67,7 @@ contract('BlacklistTransferManager', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = web3.utils.toWei("1000"); // BlacklistTransferManager details const holderCount = 2; // Maximum number of token holders @@ -171,9 +171,9 @@ contract('BlacklistTransferManager', accounts => { }); it("Should successfully attach the BlacklistTransferManager factory with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await I_PolyToken.getTokens(web3.utils.toWei("2000", "ether"), token_owner); await catchRevert ( - I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("2000", "ether"), 0, { from: token_owner }) ); @@ -181,8 +181,8 @@ contract('BlacklistTransferManager', accounts => { 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 }); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("2000", "ether"), {from: token_owner}); + const tx = await I_SecurityToken.addModule(P_BlacklistTransferManagerFactory.address, bytesSTO, web3.utils.toWei("2000", "ether"), 0, { from: token_owner }); assert.equal(tx.logs[3].args._types[0].toString(), transferManagerKey, "BlacklistTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index 194287801..fbec6e51b 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -98,7 +98,7 @@ contract('GeneralPermissionManager', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = web3.utils.toWei("1000"); let _details = "details holding for test"; let testRepeat = 20; @@ -210,19 +210,19 @@ contract('GeneralPermissionManager', accounts => { 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 I_PolyToken.getTokens(web3.utils.toWei("2000", "ether"), token_owner); await catchRevert( - I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x0", web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x0", web3.utils.toWei("2000", "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 }); + await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("2000", "ether"), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_GeneralPermissionManagerFactory.address, "0x0", - web3.utils.toWei("500", "ether"), + web3.utils.toWei("2000", "ether"), 0, { from: token_owner } ); diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 0cf2fc02f..5aac12df8 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -74,7 +74,7 @@ contract('VolumeRestrictionTransferManager', accounts => { let tempArrayGlobal = new Array(); // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = web3.utils.toWei("1000"); async function print(data, account) { console.log(` diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 7f7933801..98f2ecbe3 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -90,7 +90,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); // CountTransferManager details const holderCount = 2; // Maximum number of token holders @@ -204,9 +204,9 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { 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(new BN(web3.utils.toWei("500", "ether")), token_owner); + await I_PolyToken.getTokens(new BN(web3.utils.toWei("2000", "ether")), token_owner); await catchRevert( - I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", new BN(web3.utils.toWei("500", "ether")), new BN(0), { + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner }) ); @@ -214,11 +214,11 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { it("Should successfully attach the General permission manager factory with the security token - paid module", async () => { let snapId = await takeSnapshot(); - await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("500", "ether")), { from: token_owner }); + await I_PolyToken.transfer(I_SecurityToken.address, new BN(web3.utils.toWei("2000", "ether")), { from: token_owner }); const tx = await I_SecurityToken.addModule( P_GeneralPermissionManagerFactory.address, "0x", - new BN(web3.utils.toWei("500", "ether")), + new BN(web3.utils.toWei("2000", "ether")), new BN(0), { from: token_owner } ); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index b5aba3441..52252a62c 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -65,7 +65,7 @@ contract('VestingEscrowWallet', accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); let currentTime; const address_zero = "0x0000000000000000000000000000000000000000"; @@ -123,7 +123,7 @@ contract('VestingEscrowWallet', accounts => { STFactory: ${I_STFactory.address} GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} - + I_VestingEscrowWalletFactory: ${I_VestingEscrowWalletFactory.address} ----------------------------------------------------------------------------- `); diff --git a/test/za_datastore.js b/test/za_datastore.js index b89646bac..aa3860151 100644 --- a/test/za_datastore.js +++ b/test/za_datastore.js @@ -41,7 +41,7 @@ contract("Data store", async (accounts) => { const bytes32data2 = "0x4400000000000000000000000000000000000000000000000000000000000000"; // Initial fee for ticker registry and security token registry - const initRegFee = new BN(web3.utils.toWei("250")); + const initRegFee = new BN(web3.utils.toWei("1000")); const address_zero = "0x0000000000000000000000000000000000000000"; const address_one = "0x0000000000000000000000000000000000000001"; @@ -422,7 +422,7 @@ contract("Data store", async (accounts) => { }); it("Should not allow unauthorized addresses to delete bytes32 from Array", async () => { - await catchRevert(I_DataStore.deleteBytes32(key, 0, { from: account_polymath })); + await catchRevert(I_DataStore.deleteBytes32(key, 0, { from: account_polymath })); }); it("Should not allow unauthorized addresses to delete address from Array", async () => { @@ -465,4 +465,4 @@ contract("Data store", async (accounts) => { await catchRevert(I_DataStore.insertBoolMulti([key, key2], [true, true], { from: account_polymath })); }); }); -}); \ No newline at end of file +}); diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index a35baba07..88b8a7428 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -64,7 +64,7 @@ contract("SignedTransferManager", accounts => { const stoKey = 3; // Initial fee for ticker registry and security token registry - const initRegFee = web3.utils.toWei("250"); + const initRegFee = web3.utils.toWei("1000"); let currentTime; @@ -188,7 +188,7 @@ contract("SignedTransferManager", accounts => { it("Should successfully attach the SignedTransferManager with the security token", async () => { - const tx = await I_SecurityToken.addModule(I_SignedTransferManagerFactory.address, new BN(0),new BN(0),new BN(0), { from: token_owner }); + const tx = await I_SecurityToken.addModule(I_SignedTransferManagerFactory.address, "0x0",new BN(0),new BN(0), { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "SignedTransferManager doesn't get deployed"); assert.equal( web3.utils.toUtf8(tx.logs[2].args._name), From 45933ee35253007fdf32acd3d4643e5f6fad3307 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 11 Feb 2019 08:52:52 -0400 Subject: [PATCH 105/119] Stable oracle (#546) * WIP * Fix deployment * Update test cases for stable oracle * Bug fix --- contracts/SecurityTokenRegistry.sol | 17 +++- contracts/interfaces/IModuleFactory.sol | 2 +- contracts/interfaces/IOracle.sol | 2 +- contracts/libraries/TokenLib.sol | 29 +----- contracts/mocks/MockOracle.sol | 2 +- contracts/modules/ModuleFactory.sol | 4 +- contracts/modules/STO/USDTieredSTO.sol | 6 +- contracts/oracles/MakerDAOOracle.sol | 2 +- contracts/oracles/PolyOracle.sol | 2 +- contracts/oracles/StableOracle.sol | 113 ++++++++++++++++++++++++ contracts/tokens/SecurityToken.sol | 42 ++++----- migrations/2_deploy_contracts.js | 47 ++++++++-- test/helpers/createInstances.js | 10 ++- test/n_security_token_registry.js | 61 ++++++++++++- test/p_usd_tiered_sto.js | 16 ++-- 15 files changed, 275 insertions(+), 80 deletions(-) create mode 100644 contracts/oracles/StableOracle.sol diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index dfd7eca32..bfffbc535 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -76,7 +76,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { bytes32 constant POLYMATHREGISTRY = 0x90eeab7c36075577c7cc5ff366e389fefa8a18289b949bab3529ab4471139d4d; bytes32 constant STRGETTER = 0x982f24b3bd80807ec3cb227ba152e15c07d66855fa8ae6ca536e689205c0e2e9; - string constant POLY_ORACLE = "PolyUsdOracle"; + string constant POLY_ORACLE = "StablePolyUsdOracle"; // Emit when network becomes paused event Pause(uint256 _timestammp); @@ -214,13 +214,22 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { /** * @notice Converts USD fees into POLY amounts */ - function _takeFee(bytes32 _feeType) internal returns (uint256, uint256){ + function _takeFee(bytes32 _feeType) internal returns (uint256, uint256) { + (uint256 usdFee, uint256 polyFee) = getFees(_feeType); + if (polyFee > 0) + require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), polyFee), "Insufficent allowance"); + return (usdFee, polyFee); + } + + /** + * @notice Returns the usd & poly fee for a particular feetype + * @param _feeType Key corresponding to fee type + */ + function getFees(bytes32 _feeType) public returns (uint256, uint256) { address polymathRegistry = getAddressValue(POLYMATHREGISTRY); uint256 polyRate = IOracle(IPolymathRegistry(polymathRegistry).getAddress(POLY_ORACLE)).getPrice(); uint256 usdFee = getUintValue(_feeType); uint256 polyFee = DecimalMath.div(usdFee, polyRate); - if (polyFee > 0) - require(IERC20(getAddressValue(POLYTOKEN)).transferFrom(msg.sender, address(this), polyFee), "Insufficent allowance"); return (usdFee, polyFee); } diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 9af977287..8a988c3a3 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -67,7 +67,7 @@ interface IModuleFactory { /** * @notice Get the setup cost of the module */ - function getSetupCostInPoly() external view returns (uint256); + function getSetupCostInPoly() external returns (uint256); /** * @notice Used to get the lower bound diff --git a/contracts/interfaces/IOracle.sol b/contracts/interfaces/IOracle.sol index dc8205a2b..704814a5a 100644 --- a/contracts/interfaces/IOracle.sol +++ b/contracts/interfaces/IOracle.sol @@ -19,6 +19,6 @@ interface IOracle { /** * @notice Returns price - should throw if not valid */ - function getPrice() external view returns(uint256); + function getPrice() external returns(uint256); } diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 8585a3dba..18567243f 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -1,6 +1,5 @@ pragma solidity ^0.5.0; -import "../modules/PermissionManager/IPermissionManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../interfaces/IPoly.sol"; @@ -157,30 +156,6 @@ library TokenLib { emit ModuleBudgetChanged(_modulesToData[_module].moduleTypes, _module, currentAllowance, newAllowance); } - /** - * @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 - * @param _delegate is the address of the delegate - * @param _module is the address of the PermissionManager module - * @param _perm is the permissions data - * @return success - */ - function checkPermission(address[] storage _modules, address _delegate, address _module, bytes32 _perm) public view returns(bool) { - if (_modules.length == 0) { - return false; - } - - for (uint8 i = 0; i < _modules.length; i++) { - if (IPermissionManager(_modules[i]).checkPermission(_delegate, _module, _perm)) { - return true; - } - } - - return false; - } - /** * @notice Queries a value at a defined checkpoint * @param _checkpoints is array of Checkpoint objects @@ -256,8 +231,8 @@ library TokenLib { uint256 _value, uint256 _balanceTo, uint256 _balanceFrom - ) - public + ) + public { if ((_value == 0) || (_from == _to)) { return; diff --git a/contracts/mocks/MockOracle.sol b/contracts/mocks/MockOracle.sol index 8208f8024..511c1ef5b 100644 --- a/contracts/mocks/MockOracle.sol +++ b/contracts/mocks/MockOracle.sol @@ -43,7 +43,7 @@ contract MockOracle is IOracle { /** * @notice Returns price - should throw if not valid */ - function getPrice() external view returns(uint256) { + function getPrice() external returns(uint256) { return price; } diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index bc053e355..15e9f6cd9 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -23,7 +23,7 @@ contract ModuleFactory is IModuleFactory, Ownable { bytes32 public name; string public title; - string constant POLY_ORACLE = "PolyUsdOracle"; + string constant POLY_ORACLE = "StablePolyUsdOracle"; // @notice Allow only two variables to be stored // 1. lowerBound @@ -142,7 +142,7 @@ contract ModuleFactory is IModuleFactory, Ownable { /** * @notice Get the setup cost of the module */ - function getSetupCostInPoly() public view returns (uint256) { + function getSetupCostInPoly() public returns (uint256) { uint256 polyRate = IOracle(IPolymathRegistry(polymathRegistry).getAddress(POLY_ORACLE)).getPrice(); return DecimalMath.div(setupCost, polyRate); } diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index bd64aaca6..18231229c 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -598,7 +598,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { * @dev returns current conversion rate of funds * @param _fundRaiseType Fund raise type to get rate of */ - function getRate(FundRaiseType _fundRaiseType) public view returns (uint256) { + function getRate(FundRaiseType _fundRaiseType) public returns (uint256) { if (_fundRaiseType == FundRaiseType.ETH) { return IOracle(_getOracle(bytes32("ETH"), bytes32("USD"))).getPrice(); } else if (_fundRaiseType == FundRaiseType.POLY) { @@ -614,7 +614,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { * @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) public returns(uint256) { return DecimalMath.mul(_amount, getRate(_fundRaiseType)); } @@ -624,7 +624,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { * @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) public returns(uint256) { return DecimalMath.div(_amount, getRate(_fundRaiseType)); } diff --git a/contracts/oracles/MakerDAOOracle.sol b/contracts/oracles/MakerDAOOracle.sol index 85da5d7b6..5a390cf72 100644 --- a/contracts/oracles/MakerDAOOracle.sol +++ b/contracts/oracles/MakerDAOOracle.sol @@ -65,7 +65,7 @@ contract MakerDAOOracle is IOracle, Ownable { /** * @notice Returns price - should throw if not valid */ - function getPrice() external view returns(uint256) { + function getPrice() external returns(uint256) { if (manualOverride) { return manualPrice; } diff --git a/contracts/oracles/PolyOracle.sol b/contracts/oracles/PolyOracle.sol index f25cd7971..5c7e4c856 100644 --- a/contracts/oracles/PolyOracle.sol +++ b/contracts/oracles/PolyOracle.sol @@ -265,7 +265,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { /** * @notice Returns price - should throw if not valid */ - function getPrice() external view returns(uint256) { + function getPrice() external returns(uint256) { /*solium-disable-next-line security/no-block-members*/ require(latestUpdate >= now - staleTime, "Invalid price"); return POLYUSD; diff --git a/contracts/oracles/StableOracle.sol b/contracts/oracles/StableOracle.sol new file mode 100644 index 000000000..aeb38b4af --- /dev/null +++ b/contracts/oracles/StableOracle.sol @@ -0,0 +1,113 @@ +pragma solidity ^0.5.0; + +import "../interfaces/IOracle.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +contract StableOracle is IOracle, Ownable { + using SafeMath for uint256; + + IOracle public oracle; + uint256 public lastPrice; + uint256 public evictPercentage; //% multiplid by 10**16 + + bool public manualOverride; + uint256 public manualPrice; + + /*solium-disable-next-line security/no-block-members*/ + event ChangeOracle(address _oldOracle, address _newOracle); + event ChangeEvictPercentage(uint256 _oldEvictPercentage, uint256 _newEvictPercentage); + event SetManualPrice(uint256 _oldPrice, uint256 _newPrice, uint256 _time); + event SetManualOverride(bool _override, uint256 _time); + + /** + * @notice Creates a new stable oracle based on existing oracle + * @param _oracle address of underlying oracle + */ + constructor(address _oracle, uint256 _evictPercentage) public { + require(_oracle != address(0), "Invalid oracle"); + oracle = IOracle(_oracle); + evictPercentage = _evictPercentage; + } + + /** + * @notice Updates medianizer address + * @param _oracle Address of underlying oracle + */ + function changeOracle(address _oracle) public onlyOwner { + require(_oracle != address(0), "Invalid oracle"); + /*solium-disable-next-line security/no-block-members*/ + emit ChangeOracle(address(oracle), _oracle); + oracle = IOracle(_oracle); + } + + /** + * @notice Updates eviction percentage + * @param _evictPercentage Percentage multiplied by 10**16 + */ + function changeEvictPercentage(uint256 _evictPercentage) public onlyOwner { + emit ChangeEvictPercentage(evictPercentage, _evictPercentage); + evictPercentage = _evictPercentage; + } + + /** + * @notice Returns address of oracle currency (0x0 for ETH) + */ + function getCurrencyAddress() external view returns(address) { + return oracle.getCurrencyAddress(); + } + + /** + * @notice Returns symbol of oracle currency (0x0 for ETH) + */ + function getCurrencySymbol() external view returns(bytes32) { + return oracle.getCurrencySymbol(); + } + + /** + * @notice Returns denomination of price + */ + function getCurrencyDenominated() external view returns(bytes32) { + return oracle.getCurrencyDenominated(); + } + + /** + * @notice Returns price - should throw if not valid + */ + function getPrice() external returns(uint256) { + if (manualOverride) { + return manualPrice; + } + uint256 currentPrice = oracle.getPrice(); + if ((lastPrice == 0) || (_change(currentPrice, lastPrice) >= evictPercentage)) { + lastPrice = currentPrice; + } + return lastPrice; + } + + function _change(uint256 _newPrice, uint256 _oldPrice) internal pure returns(uint256) { + uint256 diff = _newPrice > _oldPrice ? _newPrice.sub(_oldPrice) : _oldPrice.sub(_newPrice); + return diff.mul(10**18).div(_oldPrice); + } + + /** + * @notice Set a manual price. NA - this will only be used if manualOverride == true + * @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; + } + + /** + * @notice Determine whether manual price is used or not + * @param _override Whether to use the manual override price or not + */ + function setManualOverride(bool _override) public onlyOwner { + manualOverride = _override; + /*solium-disable-next-line security/no-block-members*/ + emit SetManualOverride(_override, now); + } + +} diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 1bb6c9534..1351be50d 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -7,6 +7,7 @@ import "../interfaces/IModuleFactory.sol"; import "../interfaces/IModuleRegistry.sol"; import "../interfaces/IFeatureRegistry.sol"; import "../interfaces/ITransferManager.sol"; +import "../modules/PermissionManager/IPermissionManager.sol"; import "../RegistryUpdater.sol"; import "../libraries/Util.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; @@ -200,9 +201,9 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _granularity, string memory _tokenDetails, address _polymathRegistry - ) - public - ERC20Detailed(_name, _symbol, _decimals) RegistryUpdater(_polymathRegistry) + ) + public + ERC20Detailed(_name, _symbol, _decimals) RegistryUpdater(_polymathRegistry) { //When it is created, the owner is the STR updateFromRegistry(); @@ -227,9 +228,9 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _maxCost, uint256 _budget, bytes32 _label - ) - public - onlyOwner nonReentrant + ) + public + onlyOwner nonReentrant { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); @@ -571,10 +572,10 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _value, bytes memory _data, bool _isTransfer - ) - internal - checkGranularity(_value) - returns(bool) + ) + internal + checkGranularity(_value) + returns(bool) { if (!transfersFrozen) { bool isInvalid = false; @@ -648,11 +649,11 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address _investor, uint256 _value, bytes memory _data - ) - public - onlyModuleOrOwner(MINT_KEY) - isMintingAllowed - returns(bool success) + ) + public + onlyModuleOrOwner(MINT_KEY) + isMintingAllowed + returns(bool success) { require(_updateTransfer(address(0), _investor, _value, _data), "Transfer invalid"); _mint(_investor, _value); @@ -686,12 +687,11 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) { for (uint256 i = 0; i < modules[PERMISSION_KEY].length; i++) { - if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived) return TokenLib.checkPermission( - modules[PERMISSION_KEY], - _delegate, - _module, - _perm - ); + if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived) { + if (IPermissionManager(modules[PERMISSION_KEY][i]).checkPermission(_delegate, _module, _perm)) { + return true; + } + } } return false; } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index dae22700d..0cc03e0d5 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -25,6 +25,7 @@ const FeatureRegistry = artifacts.require("./FeatureRegistry.sol"); const STFactory = artifacts.require("./tokens/STFactory.sol"); const DevPolyToken = artifacts.require("./helpers/PolyTokenFaucet.sol"); const MockOracle = artifacts.require("./MockOracle.sol"); +const StableOracle = artifacts.require("./StableOracle.sol"); const TokenLib = artifacts.require("./TokenLib.sol"); const SecurityToken = artifacts.require("./tokens/SecurityToken.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); @@ -44,6 +45,7 @@ let PolyToken; let UsdToken; let ETHOracle; let POLYOracle; +let StablePOLYOracle; module.exports = function(deployer, network, accounts) { // Ethereum account address hold by the Polymath (Act as the main account which have ownable permissions) @@ -68,11 +70,22 @@ module.exports = function(deployer, network, accounts) { web3.utils.fromAscii("USD"), new BN(5).mul(new BN(10).pow(new BN(17))), { from: PolymathAccount } - ) - .then(() => { - MockOracle.deployed().then(mockedOracle => { - POLYOracle = mockedOracle.address; - }); + ).then(() => { + return MockOracle.deployed(); + }).then(mockedOracle => { + POLYOracle = mockedOracle.address; + }).then(() => { + return deployer + .deploy( + StableOracle, + POLYOracle, + new BN(10).mul(new BN(10).pow(new BN(16))), + { from: PolymathAccount } + ); + }).then(() => { + return StableOracle.deployed(); + }).then(stableOracle => { + StablePOLYOracle = stableOracle.address; }); deployer .deploy( @@ -94,12 +107,14 @@ module.exports = function(deployer, network, accounts) { PolyToken = "0xb347b9f5b56b431b2cf4e1d90a5995f7519ca792"; // PolyToken Kovan Faucet Address POLYOracle = "0x461d98EF2A0c7Ac1416EF065840fF5d4C946206C"; // Poly Oracle Kovan Address ETHOracle = "0xCE5551FC9d43E9D2CC255139169FC889352405C8"; // ETH Oracle Kovan Address + StablePOLYOracle = ""; // TODO } else if (network === "mainnet") { web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/g5xfoQ0jFSE9S5LwM1Ei")); PolymathAccount = accounts[0]; PolyToken = "0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC"; // Mainnet PolyToken Address POLYOracle = "0x52cb4616E191Ff664B0bff247469ce7b74579D1B"; // Poly Oracle Mainnet Address ETHOracle = "0x60055e9a93aae267da5a052e95846fa9469c0e7a"; // ETH Oracle Mainnet Address + StablePOLYOracle = ""; // TODO } if (network === "coverage") { web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); @@ -108,9 +123,21 @@ module.exports = function(deployer, network, accounts) { deployer .deploy(MockOracle, PolyToken, web3.utils.fromAscii("POLY"), web3.utils.fromAscii("USD"), new BN(0.5).mul(new BN(10).pow(new BN(18))), { from: PolymathAccount }) .then(() => { - MockOracle.deployed().then(mockedOracle => { - POLYOracle = mockedOracle.address; - }); + return MockOracle.deployed(); + }).then(mockedOracle => { + POLYOracle = mockedOracle.address; + }).then(() => { + return deployer + .deploy( + StableOracle, + POLYOracle, + new BN(10).mul(new BN(10).pow(new BN(16))), + { from: PolymathAccount } + ) + }).then(() => { + return StableOracle.deployed(); + }).then(stableOracle => { + StablePOLYOracle = stableOracle.address; }); deployer.deploy(MockOracle, nullAddress, web3.utils.fromAscii("ETH"), web3.utils.fromAscii("USD"), new BN(500).mul(new BN(10).pow(new BN(18))), { from: PolymathAccount }).then(() => { MockOracle.deployed().then(mockedOracle => { @@ -491,6 +518,9 @@ module.exports = function(deployer, network, accounts) { .then(() => { return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, { from: PolymathAccount }); }) + .then(() => { + return polymathRegistry.changeAddress("StablePolyUsdOracle", StablePOLYOracle, { from: PolymathAccount }); + }) .then(() => { return deployer.deploy(SecurityToken, "a", "a", 18, 1, "a", polymathRegistry.address, { from: PolymathAccount }); }) @@ -507,6 +537,7 @@ module.exports = function(deployer, network, accounts) { ETHOracle: ${ETHOracle} POLYOracle: ${POLYOracle} + POLYStableOracle: ${StablePOLYOracle} STFactory: ${STFactory.address} GeneralTransferManagerLogic: ${GeneralTransferManagerLogic.address} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 1c3a0fe6b..8adb680b8 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -2,6 +2,7 @@ import { encodeProxyCall, encodeModuleCall } from "./encodeCall"; const PolymathRegistry = artifacts.require("./PolymathRegistry.sol"); const MockOracle = artifacts.require("./MockOracle.sol"); +const StableOracle = artifacts.require("./StableOracle.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); @@ -103,6 +104,7 @@ let I_STRGetter; let I_SignedTransferManagerFactory; let I_USDOracle; let I_POLYOracle; +let I_StablePOLYOracle; // Initial fee for ticker registry and security token registry const initRegFee = new BN(web3.utils.toWei("250")); @@ -147,7 +149,10 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_USDOracle, + I_POLYOracle, + I_StablePOLYOracle ); return Promise.all(tempArray); } @@ -155,10 +160,13 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { export async function addOracles(account_polymath) { let USDETH = new BN(500).mul(new BN(10).pow(new BN(18))); // 500 USD/ETH let USDPOLY = new BN(25).mul(new BN(10).pow(new BN(16))); // 0.25 USD/POLY + let StableChange = new BN(10).mul(new BN(10).pow(new BN(16))); // 0.25 USD/POLY I_USDOracle = await MockOracle.new("0x0000000000000000000000000000000000000000", web3.utils.fromAscii("ETH"), web3.utils.fromAscii("USD"), USDETH, { from: account_polymath }); // 500 dollars per POLY I_POLYOracle = await MockOracle.new(I_PolyToken.address, web3.utils.fromAscii("POLY"), web3.utils.fromAscii("USD"), USDPOLY, { from: account_polymath }); // 25 cents per POLY + I_StablePOLYOracle = await StableOracle.new(I_POLYOracle.address, StableChange, { from: account_polymath }); await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: account_polymath }); await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: account_polymath }); + await I_PolymathRegistry.changeAddress("StablePolyUsdOracle", I_StablePOLYOracle.address, { from: account_polymath }); } export async function deployPolyRegistryAndPolyToken(account_polymath, token_owner) { diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index a7d19c13c..fd2fbeb7e 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -61,6 +61,9 @@ contract("SecurityTokenRegistry", async (accounts) => { let I_MRProxied; let I_STRGetter; let I_Getter; + let I_USDOracle; + let I_POLYOracle; + let I_StablePOLYOracle; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -120,7 +123,10 @@ contract("SecurityTokenRegistry", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_USDOracle, + I_POLYOracle, + I_StablePOLYOracle ] = instances; // STEP 8: Deploy the CappedSTOFactory @@ -357,6 +363,59 @@ contract("SecurityTokenRegistry", async (accounts) => { assert.equal(data[3], ""); }); + it("Should change ticker price based on oracle", async () => { + let snap_Id = await takeSnapshot(); + let origPriceUSD = new BN(web3.utils.toWei("250")); + let origPricePOLY = new BN(web3.utils.toWei("1000")); + let currentRate = await I_POLYOracle.getPrice.call(); + console.log("Current Rate: " + currentRate); + let feesTicker = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + let feesToken = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + assert.equal(feesTicker[0].toString(), origPriceUSD.toString()); + assert.equal(feesTicker[1].toString(), origPricePOLY.toString()); + assert.equal(feesToken[0].toString(), origPriceUSD.toString()); + assert.equal(feesToken[1].toString(), origPricePOLY.toString()); + await I_POLYOracle.changePrice(new BN(27).mul(new BN(10).pow(new BN(16)))); + await I_STRProxied.getFees("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesTicker = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesToken = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + // No change as difference is less than 10% + assert.equal(feesTicker[0].toString(), origPriceUSD.toString()); + assert.equal(feesTicker[1].toString(), origPricePOLY.toString()); + assert.equal(feesToken[0].toString(), origPriceUSD.toString()); + assert.equal(feesToken[1].toString(), origPricePOLY.toString()); + await I_POLYOracle.changePrice(new BN(20).mul(new BN(10).pow(new BN(16)))); + await I_STRProxied.getFees("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesTicker = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesToken = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + let newPricePOLY = new BN(web3.utils.toWei("1250")); + assert.equal(feesTicker[0].toString(), origPriceUSD.toString()); + assert.equal(feesTicker[1].toString(), newPricePOLY.toString()); + assert.equal(feesToken[0].toString(), origPriceUSD.toString()); + assert.equal(feesToken[1].toString(), newPricePOLY.toString()); + await I_POLYOracle.changePrice(new BN(21).mul(new BN(10).pow(new BN(16)))); + await I_STRProxied.getFees("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesTicker = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesToken = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + // No change as difference is less than 10% + assert.equal(feesTicker[0].toString(), origPriceUSD.toString()); + assert.equal(feesTicker[1].toString(), newPricePOLY.toString()); + assert.equal(feesToken[0].toString(), origPriceUSD.toString()); + assert.equal(feesToken[1].toString(), newPricePOLY.toString()); + await I_StablePOLYOracle.changeEvictPercentage(new BN(10).pow(new BN(16))); + await I_STRProxied.getFees("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesTicker = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + feesToken = await I_STRProxied.getFees.call("0x2fcc69711628630fb5a42566c68bd1092bc4aa26826736293969fddcd11cb2d2"); + // Change as eviction percentage updated + // newPricePOLY = new BN(web3.utils.toWei("1250")); + //1190.476190476190476190 = 250/0.21 + assert.equal(feesTicker[0].toString(), origPriceUSD.toString()); + assert.equal(feesTicker[1].toString(), "1190476190476190476190"); + assert.equal(feesToken[0].toString(), origPriceUSD.toString()); + assert.equal(feesToken[1].toString(), "1190476190476190476190"); + await revertToSnapshot(snap_Id); + }); + it("Should register the ticker when the tickerRegFee is 0", async () => { let snap_Id = await takeSnapshot(); await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 7946512a8..1da3d9f20 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -179,18 +179,18 @@ contract("USDTieredSTO", async (accounts) => { .div(e18); if (_currencyTo == "USD") return tokenToUSD; if (_currencyTo == "ETH") { - return await I_USDTieredSTO_Array[_stoID].convertFromUSD(ETH, tokenToUSD); + return await I_USDTieredSTO_Array[_stoID].convertFromUSD.call(ETH, tokenToUSD); } else if (_currencyTo == "POLY") { - return await I_USDTieredSTO_Array[_stoID].convertFromUSD(POLY, tokenToUSD); + return await I_USDTieredSTO_Array[_stoID].convertFromUSD.call(POLY, tokenToUSD); } } if (_currencyFrom == "USD") { if (_currencyTo == "TOKEN") return _amount.div(USDTOKEN).mul(e18); // USD / USD/TOKEN = TOKEN if (_currencyTo == "ETH" || _currencyTo == "POLY") - return await I_USDTieredSTO_Array[_stoID].convertFromUSD(_currencyTo == "ETH" ? ETH : POLY, _amount); + return await I_USDTieredSTO_Array[_stoID].convertFromUSD.call(_currencyTo == "ETH" ? ETH : POLY, _amount); } if (_currencyFrom == "ETH" || _currencyFrom == "POLY") { - let ethToUSD = await I_USDTieredSTO_Array[_stoID].convertToUSD(_currencyTo == "ETH" ? ETH : POLY, _amount); + let ethToUSD = await I_USDTieredSTO_Array[_stoID].convertToUSD.call(_currencyTo == "ETH" ? ETH : POLY, _amount); if (_currencyTo == "USD") return ethToUSD; if (_currencyTo == "TOKEN") return ethToUSD.div(USDTOKEN).mul(e18); // USD / USD/TOKEN = TOKEN } @@ -4596,7 +4596,7 @@ contract("USDTieredSTO", async (accounts) => { it("should get the right conversion for ETH to USD", async () => { // 20 ETH to 10000 USD let ethInWei = new BN(web3.utils.toWei("20", "ether")); - let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(ETH, ethInWei); + let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD.call(ETH, ethInWei); assert.equal( usdInWei.div(e18).toString(), ethInWei @@ -4609,7 +4609,7 @@ contract("USDTieredSTO", async (accounts) => { it("should get the right conversion for POLY to USD", async () => { // 40000 POLY to 10000 USD let polyInWei = new BN(web3.utils.toWei("40000", "ether")); - let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD(POLY, polyInWei); + let usdInWei = await I_USDTieredSTO_Array[0].convertToUSD.call(POLY, polyInWei); assert.equal( usdInWei.toString(), polyInWei @@ -4624,7 +4624,7 @@ contract("USDTieredSTO", async (accounts) => { it("should get the right conversion for USD to ETH", async () => { // 10000 USD to 20 ETH let usdInWei = new BN(web3.utils.toWei("10000", "ether")); - let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD(ETH, usdInWei); + let ethInWei = await I_USDTieredSTO_Array[0].convertFromUSD.call(ETH, usdInWei); assert.equal( ethInWei.div(e18).toString(), usdInWei @@ -4637,7 +4637,7 @@ contract("USDTieredSTO", async (accounts) => { it("should get the right conversion for USD to POLY", async () => { // 10000 USD to 40000 POLY let usdInWei = new BN(web3.utils.toWei("10000", "ether")); - let polyInWei = await I_USDTieredSTO_Array[0].convertFromUSD(POLY, usdInWei); + let polyInWei = await I_USDTieredSTO_Array[0].convertFromUSD.call(POLY, usdInWei); assert.equal( polyInWei.toString(), usdInWei.mul(e18).div(USDPOLY).toString() From 5ed9ace2cfc1e454a53125a71ef6e3a081055d2e Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 12 Feb 2019 15:02:22 +0530 Subject: [PATCH 106/119] remove timestamps from the events --- contracts/ModuleRegistry.sol | 8 ++--- contracts/Pausable.sol | 8 ++--- contracts/SecurityTokenRegistry.sol | 8 ++--- contracts/libraries/TokenLib.sol | 12 ++++---- .../modules/Checkpoint/DividendCheckpoint.sol | 16 +++++----- .../Experimental/Burn/TrackedRedemption.sol | 4 +-- .../Mixed/ScheduledCheckpoint.sol | 8 ++--- .../GeneralPermissionManager.sol | 8 ++--- .../PercentageTransferManager.sol | 4 +-- contracts/oracles/MakerDAOOracle.sol | 12 ++++---- contracts/oracles/PolyOracle.sol | 4 +-- contracts/oracles/StableOracle.sol | 8 ++--- contracts/tokens/SecurityToken.sol | 29 +++++++++---------- 13 files changed, 64 insertions(+), 65 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index d90527993..974d5310d 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -40,9 +40,9 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { ////////// // Emit when network becomes paused - event Pause(uint256 _timestammp); + event Pause(address account); // Emit when network becomes unpaused - event Unpause(uint256 _timestamp); + event Unpause(address account); // Emit when Module is used by the SecurityToken event ModuleUsed(address indexed _moduleFactory, address indexed _securityToken); // Emit when the Module Factory gets registered on the ModuleRegistry contract @@ -359,7 +359,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); + emit Pause(msg.sender); } /** @@ -368,7 +368,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); + emit Unpause(msg.sender); } /** diff --git a/contracts/Pausable.sol b/contracts/Pausable.sol index 996275e5c..184987439 100644 --- a/contracts/Pausable.sol +++ b/contracts/Pausable.sol @@ -4,8 +4,8 @@ pragma solidity ^0.5.0; * @title Utility contract to allow pausing and unpausing of certain functions */ contract Pausable { - event Pause(uint256 _timestammp); - event Unpause(uint256 _timestamp); + event Pause(address account); + event Unpause(address account); bool public paused = false; @@ -31,7 +31,7 @@ contract Pausable { function _pause() internal whenNotPaused { paused = true; /*solium-disable-next-line security/no-block-members*/ - emit Pause(now); + emit Pause(msg.sender); } /** @@ -40,7 +40,7 @@ contract Pausable { function _unpause() internal whenPaused { paused = false; /*solium-disable-next-line security/no-block-members*/ - emit Unpause(now); + emit Unpause(msg.sender); } } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index bfffbc535..88c9d31d5 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -79,9 +79,9 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { string constant POLY_ORACLE = "StablePolyUsdOracle"; // Emit when network becomes paused - event Pause(uint256 _timestammp); + event Pause(address account); // Emit when network becomes unpaused - event Unpause(uint256 _timestamp); + event Unpause(address account); // Emit when the ticker is removed from the registry event TickerRemoved(string _ticker, uint256 _removedAt, address _removedBy); // Emit when the token ticker expiry is changed @@ -605,7 +605,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { function pause() external whenNotPaused onlyOwner { set(PAUSED, true); /*solium-disable-next-line security/no-block-members*/ - emit Pause(now); + emit Pause(msg.sender); } /** @@ -614,7 +614,7 @@ contract SecurityTokenRegistry is EternalStorage, Proxy { function unpause() external whenPaused onlyOwner { set(PAUSED, false); /*solium-disable-next-line security/no-block-members*/ - emit Unpause(now); + emit Unpause(msg.sender); } /** diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 18567243f..239c57941 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -34,11 +34,11 @@ library TokenLib { } // Emit when Module is archived from the SecurityToken - event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp); + event ModuleArchived(uint8[] _types, address _module); // Emit when Module is unarchived from the SecurityToken - event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp); + event ModuleUnarchived(uint8[] _types, address _module); // Emit when Module get removed from the securityToken - event ModuleRemoved(uint8[] _types, address _module, uint256 _timestamp); + event ModuleRemoved(uint8[] _types, address _module); // Emit when the budget allocated to a module is changed event ModuleBudgetChanged(uint8[] _moduleTypes, address _module, uint256 _oldBudget, uint256 _budget); @@ -51,7 +51,7 @@ library TokenLib { 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); + emit ModuleArchived(_moduleData.moduleTypes, _module); _moduleData.isArchived = true; } @@ -63,7 +63,7 @@ library TokenLib { 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); + emit ModuleUnarchived(_moduleData.moduleTypes, _module); _moduleData.isArchived = false; } @@ -82,7 +82,7 @@ library TokenLib { 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); + emit ModuleRemoved(_modulesToData[_module].moduleTypes, _module); // Remove from module type list uint8[] memory moduleTypes = _modulesToData[_module].moduleTypes; for (uint256 i = 0; i < moduleTypes.length; i++) { diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index 3bfc358d8..e4e0d7dfb 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -20,10 +20,10 @@ import "openzeppelin-solidity/contracts/math/Math.sol"; 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); - event SetWallet(address indexed _oldWallet, address indexed _newWallet, uint256 _timestamp); + event SetDefaultExcludedAddresses(address[] _excluded); + event SetWithholding(address[] _investors, uint256[] _withholding); + event SetWithholdingFixed(address[] _investors, uint256 _withholding); + event SetWallet(address indexed _oldWallet, address indexed _newWallet); modifier validDividendIndex(uint256 _dividendIndex) { require(_dividendIndex < dividends.length, "Invalid dividend"); @@ -63,7 +63,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { function _setWallet(address payable _wallet) internal { require(_wallet != address(0)); - emit SetWallet(wallet, _wallet, now); + emit SetWallet(wallet, _wallet); wallet = _wallet; } @@ -97,7 +97,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { } excluded = _excluded; /*solium-disable-next-line security/no-block-members*/ - emit SetDefaultExcludedAddresses(excluded, now); + emit SetDefaultExcludedAddresses(excluded); } /** @@ -108,7 +108,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { function setWithholding(address[] memory _investors, uint256[] memory _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); + emit SetWithholding(_investors, _withholding); for (uint256 i = 0; i < _investors.length; i++) { require(_withholding[i] <= 10 ** 18, "Incorrect withholding tax"); withholdingTax[_investors[i]] = _withholding[i]; @@ -123,7 +123,7 @@ contract DividendCheckpoint is DividendCheckpointStorage, ICheckpoint, Module { function setWithholdingFixed(address[] memory _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); + emit SetWithholdingFixed(_investors, _withholding); for (uint256 i = 0; i < _investors.length; i++) { withholdingTax[_investors[i]] = _withholding; } diff --git a/contracts/modules/Experimental/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol index eda7ca14c..e6af32d43 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -12,7 +12,7 @@ contract TrackedRedemption is IBurn, Module { mapping(address => uint256) redeemedTokens; - event Redeemed(address _investor, uint256 _value, uint256 _timestamp); + event Redeemed(address _investor, uint256 _value); /** * @notice Constructor @@ -37,7 +37,7 @@ contract TrackedRedemption is IBurn, Module { 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); + emit Redeemed(msg.sender, _value); } /** diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index 9cc14c730..f0d1cbc9c 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -25,8 +25,8 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { mapping(bytes32 => Schedule) public schedules; - event AddSchedule(bytes32 _name, uint256 _startTime, uint256 _interval, uint256 _timestamp); - event RemoveSchedule(bytes32 _name, uint256 _timestamp); + event AddSchedule(bytes32 _name, uint256 _startTime, uint256 _interval); + event RemoveSchedule(bytes32 _name); /** * @notice Constructor @@ -58,7 +58,7 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { schedules[_name].interval = _interval; schedules[_name].index = names.length; names.push(_name); - emit AddSchedule(_name, _startTime, _interval, now); + emit AddSchedule(_name, _startTime, _interval); } /** @@ -74,7 +74,7 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { schedules[names[index]].index = index; } delete schedules[_name]; - emit RemoveSchedule(_name, now); + emit RemoveSchedule(_name); } /** diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 6ce855897..39b09050b 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -10,9 +10,9 @@ import "./GeneralPermissionManagerStorage.sol"; contract GeneralPermissionManager is GeneralPermissionManagerStorage, 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); + event ChangePermission(address indexed _delegate, address _module, bytes32 _perm, bool _valid); /// Used to notify when delegate is added in permission manager contract - event AddDelegate(address indexed _delegate, bytes32 _details, uint256 _timestamp); + event AddDelegate(address indexed _delegate, bytes32 _details); /// @notice constructor constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { @@ -52,7 +52,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio delegateDetails[_delegate] = _details; allDelegates.push(_delegate); /*solium-disable-next-line security/no-block-members*/ - emit AddDelegate(_delegate, _details, now); + emit AddDelegate(_delegate, _details); } /** @@ -207,7 +207,7 @@ contract GeneralPermissionManager is GeneralPermissionManagerStorage, IPermissio function _changePermission(address _delegate, address _module, bytes32 _perm, bool _valid) internal { perms[_module][_delegate][_perm] = _valid; /*solium-disable-next-line security/no-block-members*/ - emit ChangePermission(_delegate, _module, _perm, _valid, now); + emit ChangePermission(_delegate, _module, _perm, _valid); } /** diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index cdd0cc073..dbcfc5906 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -19,7 +19,7 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer event ModifyHolderPercentage(uint256 _oldHolderPercentage, uint256 _newHolderPercentage); event ModifyWhitelist(address _investor, uint256 _dateAdded, address _addedBy, bool _valid); - event SetAllowPrimaryIssuance(bool _allowPrimaryIssuance, uint256 _timestamp); + event SetAllowPrimaryIssuance(bool _allowPrimaryIssuance); /** * @notice Constructor @@ -117,7 +117,7 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer require(_allowPrimaryIssuance != allowPrimaryIssuance, "Must change setting"); allowPrimaryIssuance = _allowPrimaryIssuance; /*solium-disable-next-line security/no-block-members*/ - emit SetAllowPrimaryIssuance(_allowPrimaryIssuance, now); + emit SetAllowPrimaryIssuance(_allowPrimaryIssuance); } /** diff --git a/contracts/oracles/MakerDAOOracle.sol b/contracts/oracles/MakerDAOOracle.sol index 5a390cf72..f28c9e965 100644 --- a/contracts/oracles/MakerDAOOracle.sol +++ b/contracts/oracles/MakerDAOOracle.sol @@ -13,9 +13,9 @@ contract MakerDAOOracle is IOracle, Ownable { 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); + event ChangeMedianizer(address _newMedianizer, address _oldMedianizer); + event SetManualPrice(uint256 _oldPrice, uint256 _newPrice); + event SetManualOverride(bool _override); /** * @notice Creates a new Maker based oracle @@ -36,7 +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); + emit ChangeMedianizer(_medianizer, medianizer); medianizer = _medianizer; } @@ -80,7 +80,7 @@ contract MakerDAOOracle is IOracle, Ownable { */ function setManualPrice(uint256 _price) public onlyOwner { /*solium-disable-next-line security/no-block-members*/ - emit SetManualPrice(manualPrice, _price, now); + emit SetManualPrice(manualPrice, _price); manualPrice = _price; } @@ -91,7 +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); + emit SetManualOverride(_override); } } diff --git a/contracts/oracles/PolyOracle.sol b/contracts/oracles/PolyOracle.sol index 5c7e4c856..a029a11ce 100644 --- a/contracts/oracles/PolyOracle.sol +++ b/contracts/oracles/PolyOracle.sol @@ -29,7 +29,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { event PriceUpdated(uint256 _price, uint256 _oldPrice, bytes32 _queryId, uint256 _time); event NewOraclizeQuery(uint256 _time, bytes32 _queryId, string _query); - event AdminSet(address _admin, bool _valid, uint256 _time); + event AdminSet(address _admin, bool _valid); event StalePriceUpdate(bytes32 _queryId, uint256 _time, string _result); modifier isAdminOrOwner() { @@ -230,7 +230,7 @@ contract PolyOracle is usingOraclize, IOracle, Ownable { function setAdmin(address _admin, bool _valid) public onlyOwner { admin[_admin] = _valid; /*solium-disable-next-line security/no-block-members*/ - emit AdminSet(_admin, _valid, now); + emit AdminSet(_admin, _valid); } /** diff --git a/contracts/oracles/StableOracle.sol b/contracts/oracles/StableOracle.sol index aeb38b4af..3dabf26d2 100644 --- a/contracts/oracles/StableOracle.sol +++ b/contracts/oracles/StableOracle.sol @@ -17,8 +17,8 @@ contract StableOracle is IOracle, Ownable { /*solium-disable-next-line security/no-block-members*/ event ChangeOracle(address _oldOracle, address _newOracle); event ChangeEvictPercentage(uint256 _oldEvictPercentage, uint256 _newEvictPercentage); - event SetManualPrice(uint256 _oldPrice, uint256 _newPrice, uint256 _time); - event SetManualOverride(bool _override, uint256 _time); + event SetManualPrice(uint256 _oldPrice, uint256 _newPrice); + event SetManualOverride(bool _override); /** * @notice Creates a new stable oracle based on existing oracle @@ -96,7 +96,7 @@ contract StableOracle is IOracle, Ownable { */ function setManualPrice(uint256 _price) public onlyOwner { /*solium-disable-next-line security/no-block-members*/ - emit SetManualPrice(manualPrice, _price, now); + emit SetManualPrice(manualPrice, _price); manualPrice = _price; } @@ -107,7 +107,7 @@ contract StableOracle is IOracle, Ownable { function setManualOverride(bool _override) public onlyOwner { manualOverride = _override; /*solium-disable-next-line security/no-block-members*/ - emit SetManualOverride(_override, now); + emit SetManualOverride(_override); } } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 1351be50d..4da34cbdb 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -95,8 +95,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address _module, uint256 _moduleCost, uint256 _budget, - bytes32 _label, - uint256 _timestamp + bytes32 _label ); // Emit when the token details get updated @@ -104,19 +103,19 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Emit when the granularity get changed event GranularityChanged(uint256 _oldGranularity, uint256 _newGranularity); // Emit when Module get archived from the securityToken - event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp); + event ModuleArchived(uint8[] _types, address _module); // Emit when Module get unarchived from the securityToken - event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp); + event ModuleUnarchived(uint8[] _types, address _module); // Emit when Module get removed from the securityToken - event ModuleRemoved(uint8[] _types, address _module, uint256 _timestamp); + event ModuleRemoved(uint8[] _types, address _module); // Emit when the budget allocated to a module is changed event ModuleBudgetChanged(uint8[] _moduleTypes, address _module, uint256 _oldBudget, uint256 _budget); // Emit when transfers are frozen or unfrozen - event FreezeTransfers(bool _status, uint256 _timestamp); + event FreezeTransfers(bool _status); // Emit when new checkpoint created - event CheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp); + event CheckpointCreated(uint256 indexed _checkpointId); // Emit when is permanently frozen by the issuer - event FreezeMinting(uint256 _timestamp); + event FreezeMinting(); // Events to log minting and burning event Minted(address indexed _to, uint256 _value); event Burnt(address indexed _from, uint256 _value); @@ -132,7 +131,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater bytes _data ); event ForceBurn(address indexed _controller, address indexed _from, uint256 _value, bool _verifyTransfer, bytes _data); - event DisableController(uint256 _timestamp); + event DisableController(); function _isModule(address _module, uint8 _type) internal view returns(bool) { require(modulesToData[_module].module == _module, "Wrong address"); @@ -266,7 +265,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater names[moduleName].push(module); //Emit log event /*solium-disable-next-line security/no-block-members*/ - emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label, now); + emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label); } /** @@ -459,7 +458,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater require(!transfersFrozen, "Already frozen"); transfersFrozen = true; /*solium-disable-next-line security/no-block-members*/ - emit FreezeTransfers(true, now); + emit FreezeTransfers(true); } /** @@ -469,7 +468,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater require(transfersFrozen, "Not frozen"); transfersFrozen = false; /*solium-disable-next-line security/no-block-members*/ - emit FreezeTransfers(false, now); + emit FreezeTransfers(false); } /** @@ -623,7 +622,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater function freezeMinting() external isMintingAllowed isEnabled("freezeMintingAllowed") onlyOwner { mintingFrozen = true; /*solium-disable-next-line security/no-block-members*/ - emit FreezeMinting(now); + emit FreezeMinting(); } /** @@ -749,7 +748,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater checkpointTimes.push(now); /*solium-disable-next-line security/no-block-members*/ checkpointTotalSupply[currentCheckpointId] = totalSupply(); - emit CheckpointCreated(currentCheckpointId, now); + emit CheckpointCreated(currentCheckpointId); return currentCheckpointId; } @@ -800,7 +799,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater controllerDisabled = true; delete controller; /*solium-disable-next-line security/no-block-members*/ - emit DisableController(now); + emit DisableController(); } /** From 16de8043eab2bf8720498c6efd69e9de5088fc9a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Feb 2019 13:59:22 +0530 Subject: [PATCH 107/119] Updated calculate size script --- package.json | 3 +- scripts/calculateSize.js | 28 ++++++++------- yarn.lock | 76 ++++++---------------------------------- 3 files changed, 28 insertions(+), 79 deletions(-) diff --git a/package.json b/package.json index a30b1040a..12582264c 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "babel-preset-stage-3": "6.24.1", "babel-register": "6.26.0", "bignumber.js": "5.0.0", - "chalk": "^2.4.1", + "chalk": "^2.4.2", "coveralls": "^3.0.1", "ethereumjs-testrpc": "^6.0.3", "ethers": "^4.0.7", @@ -90,7 +90,6 @@ "ganache-cli": "^6.2.4", "mocha-junit-reporter": "^1.18.0", "prettier": "^1.15.3", - "prettier-plugin-solidity-refactor": "^1.0.0-alpha.10", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", diff --git a/scripts/calculateSize.js b/scripts/calculateSize.js index 997c34547..012f9e8ef 100644 --- a/scripts/calculateSize.js +++ b/scripts/calculateSize.js @@ -1,28 +1,32 @@ const fs = require("fs"); const path = require("path"); -var size = new Array(); +const exec = require('child_process').execSync; +const chalk = require('chalk'); -function readFiles() { +async function readFiles() { if (fs.existsSync("./build/contracts/")) { - let files = fs.readdirSync("./build/contracts/"); - return files; + return fs.readdirSync("./build/contracts/"); } else { - console.log("Directory doesn't exists"); + console.log('Compiling contracts. This may take a while, please wait.'); + exec('truffle compile'); + return fs.readdirSync("./build/contracts/"); } } async function printSize() { - let files = readFiles(); + let files = await readFiles(); + console.log(`NOTE- Maximum size of contracts allowed to deloyed on the Ethereum mainnet is 24 KB(EIP170)`); + console.log(`---- Size of the contracts ----`); files.forEach(item => { let content = JSON.parse(fs.readFileSync(`./build/contracts/${item}`).toString()).deployedBytecode; let sizeInKB = content.toString().length / 2 / 1024; - size.push(sizeInKB); + if (sizeInKB > 24) + console.log(chalk.red(`${path.basename(item, ".json")} - ${sizeInKB} KB`)); + else if (sizeInKB > 20) + console.log(chalk.yellow(`${path.basename(item, ".json")} - ${sizeInKB} KB`)); + else + console.log(chalk.green(`${path.basename(item, ".json")} - ${sizeInKB} KB`)); }); - console.log(`NOTE- Maximum size of contracts allowed to deloyed on the Ethereum mainnet is 24 KB(EIP170)`); - console.log(`---- Size of the contracts ----`); - for (let i = 0; i < files.length; i++) { - console.log(`${path.basename(files[i], ".json")} - ${size[i]} KB`); - } } printSize(); diff --git a/yarn.lock b/yarn.lock index 05f706a51..55a6a48db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -186,11 +186,6 @@ ansi-regex@^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" @@ -1543,7 +1538,7 @@ 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.3.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== @@ -1552,6 +1547,15 @@ 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" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2352,11 +2356,6 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emoji-regex@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.1.tgz#5a132b28ebf84a289ba692862f7d4206ebcd32d0" - integrity sha512-cjx7oFbFIyZMpmWaEBnKeJXWAVzjXwK6yHiz/5X73A2Ww4pnabw+4ZaA/MxLroIQQrB3dL6XzEz8P3aZsSdj8Q== - emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -2658,13 +2657,6 @@ espree@^4.0.0: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" -esprima-extract-comments@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" - integrity sha512-sBQUnvJwpeE9QnPrxh7dpI/dp67erYG4WXEAreAMoelPRpMR7NWb4YtwRPn9b+H1uLQKl/qS8WYmyaljTpjIsw== - dependencies: - esprima "^4.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" @@ -3162,14 +3154,6 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-comments@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" - integrity sha512-dzbZV2AdSSVW/4E7Ti5hZdHWbA+Z80RJsJhr5uiL10oyjl/gy7/o+HI1HwK4/WSZhlq4SNKU3oUzXlM13Qx02Q== - dependencies: - esprima-extract-comments "^1.1.0" - parse-code-context "^1.0.0" - extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" @@ -5549,11 +5533,6 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" -parse-code-context@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" - integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA== - parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -5752,19 +5731,7 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= -prettier-plugin-solidity-refactor@^1.0.0-alpha.10: - version "1.0.0-alpha.10" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity-refactor/-/prettier-plugin-solidity-refactor-1.0.0-alpha.10.tgz#39c783d9bae100792a71dbd9b60277fbc5cfa31b" - integrity sha512-xHZOIbYD1NYsacpGuPuCbwDbiU5nT07YPrRhkMsuulVocy15vL+XQLFyQmU+oMgeQuQLI8vW79QYw32SG08RbA== - dependencies: - emoji-regex "^7.0.1" - escape-string-regexp "^1.0.5" - extract-comments "^1.1.0" - prettier "^1.15.2" - solidity-parser-antlr "^0.3.1" - string-width "3.0.0" - -prettier@^1.15.2, prettier@^1.15.3: +prettier@^1.15.3: version "1.15.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" integrity sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg== @@ -6737,11 +6704,6 @@ solidity-docgen@^0.1.0: react-dom "^16.2.0" shelljs "^0.8.1" -solidity-parser-antlr@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.3.2.tgz#1cf9d019280550a31299dc380e87a310dc4ca154" - integrity sha512-aO/lbnc14A81cQigN5sKNuwbxohPyJOq7kpLirYT/6emCw5Gjb0TJoZ3TzL1tYdIX6gjTAMlQ1UZwOcrzOAp4w== - 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" @@ -6956,15 +6918,6 @@ 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@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" - integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.0.0" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -7024,13 +6977,6 @@ 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" - 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" From 5d1274e477c4693d5ecc4919e176ce6d36a552f6 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 14 Feb 2019 15:25:35 +0530 Subject: [PATCH 108/119] add table --- package.json | 1 + scripts/calculateSize.js | 19 +- yarn.lock | 1129 ++------------------------------------ 3 files changed, 71 insertions(+), 1078 deletions(-) diff --git a/package.json b/package.json index 12582264c..e8a7e72ef 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "ganache-cli": "^6.2.4", "mocha-junit-reporter": "^1.18.0", "prettier": "^1.15.3", + "table": "^5.2.3", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", diff --git a/scripts/calculateSize.js b/scripts/calculateSize.js index 012f9e8ef..92504c234 100644 --- a/scripts/calculateSize.js +++ b/scripts/calculateSize.js @@ -2,6 +2,7 @@ const fs = require("fs"); const path = require("path"); const exec = require('child_process').execSync; const chalk = require('chalk'); +const { table } = require("table"); async function readFiles() { if (fs.existsSync("./build/contracts/")) { @@ -17,16 +18,28 @@ async function printSize() { let files = await readFiles(); console.log(`NOTE- Maximum size of contracts allowed to deloyed on the Ethereum mainnet is 24 KB(EIP170)`); console.log(`---- Size of the contracts ----`); + let contracts = new Array(); + let size = new Array(); files.forEach(item => { let content = JSON.parse(fs.readFileSync(`./build/contracts/${item}`).toString()).deployedBytecode; let sizeInKB = content.toString().length / 2 / 1024; + size.push(sizeInKB); if (sizeInKB > 24) - console.log(chalk.red(`${path.basename(item, ".json")} - ${sizeInKB} KB`)); + contracts.push(chalk.red(path.basename(item, ".json"))); else if (sizeInKB > 20) - console.log(chalk.yellow(`${path.basename(item, ".json")} - ${sizeInKB} KB`)); + contracts.push(chalk.yellow(path.basename(item, ".json"))); else - console.log(chalk.green(`${path.basename(item, ".json")} - ${sizeInKB} KB`)); + contracts.push(chalk.green(path.basename(item, ".json"))); }); + let dataTable = [['Contracts', 'Size in KB']]; + for (let i = 0; i < contracts.length; i++) { + dataTable.push([ + contracts[i], + size[i] + ]); + } + console.log(); + console.log(table(dataTable)); } printSize(); diff --git a/yarn.lock b/yarn.lock index 55a6a48db..acb5a45dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,12 +19,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" @@ -42,31 +40,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" @@ -74,7 +67,6 @@ 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" @@ -85,12 +77,10 @@ acorn-jsx@^5.0.0: 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: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^6.0.2: version "6.0.4" @@ -99,22 +89,18 @@ 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.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== 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: 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" @@ -142,7 +128,15 @@ ajv@^6.5.3: ajv@^6.5.5: 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" + +ajv@^6.9.1: + version "6.9.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1" dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -152,7 +146,6 @@ ajv@^6.5.5: 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" @@ -161,7 +154,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" @@ -169,44 +161,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" 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" @@ -214,7 +202,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" @@ -222,17 +209,14 @@ anymatch@^2.0.0: app-module-path@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" - integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= 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" @@ -240,26 +224,22 @@ 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" @@ -268,22 +248,18 @@ arr-union@^3.1.0: 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" @@ -292,36 +268,34 @@ 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= + +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" - 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" @@ -334,54 +308,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" @@ -390,7 +354,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" @@ -415,7 +378,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" @@ -429,7 +391,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" @@ -438,7 +399,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" @@ -447,7 +407,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" @@ -457,7 +416,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" @@ -467,7 +425,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" @@ -476,7 +433,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" @@ -486,7 +442,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" @@ -497,7 +452,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" @@ -505,7 +459,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" @@ -513,7 +466,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" @@ -521,7 +473,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" @@ -530,7 +481,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" @@ -541,7 +491,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" @@ -553,7 +502,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" @@ -561,61 +509,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" @@ -624,7 +561,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" @@ -633,7 +569,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" @@ -643,7 +578,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" @@ -654,21 +588,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" @@ -679,7 +610,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" @@ -694,7 +624,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" @@ -702,14 +631,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" @@ -717,14 +644,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" @@ -733,14 +658,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" @@ -749,7 +672,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" @@ -759,7 +681,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" @@ -768,7 +689,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" @@ -777,7 +697,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" @@ -785,7 +704,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" @@ -797,7 +715,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" @@ -805,14 +722,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" @@ -821,21 +736,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" @@ -844,7 +756,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" @@ -853,7 +764,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" @@ -861,14 +771,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" @@ -876,7 +784,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" @@ -885,7 +792,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" @@ -921,7 +827,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" @@ -951,7 +856,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" @@ -961,7 +865,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" @@ -972,7 +875,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" @@ -985,7 +887,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" @@ -993,7 +894,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" @@ -1004,7 +904,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" @@ -1019,7 +918,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" @@ -1029,7 +927,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" @@ -1037,34 +934,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" @@ -1077,14 +968,12 @@ 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@5.0.0: version "5.0.0" @@ -1093,12 +982,10 @@ 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@^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#master": version "2.0.7" @@ -1115,24 +1002,20 @@ bignumber.js@^7.2.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== 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" @@ -1144,7 +1027,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" @@ -1156,7 +1038,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" @@ -1164,7 +1045,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" @@ -1172,39 +1052,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" @@ -1220,7 +1093,6 @@ body-parser@1.18.3, body-parser@^1.16.0: borc@^2.0.2: 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" @@ -1230,7 +1102,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" @@ -1238,7 +1109,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" @@ -1247,7 +1117,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" @@ -1263,22 +1132,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" @@ -1290,7 +1155,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" @@ -1299,7 +1163,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" @@ -1309,7 +1172,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" @@ -1317,14 +1179,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" @@ -1337,14 +1197,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" @@ -1352,19 +1210,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" @@ -1373,17 +1228,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" @@ -1391,37 +1243,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" @@ -1430,7 +1275,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" @@ -1439,7 +1283,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" @@ -1447,22 +1290,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" @@ -1477,34 +1316,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" @@ -1512,17 +1345,14 @@ caminte@0.3.7: caniuse-lite@^1.0.30000844: version "1.0.30000921" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000921.tgz#7a607c1623444b22351d834e093aedda3c42fbe8" - integrity sha512-Bu09ciy0lMWLgpYC77I0YGuI8eFRBPPzaSOYJK1jTI64txCphYCqnWbxJYjHABYVt/TYX/p3jNjLBR87u1Bfpw== 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" @@ -1530,7 +1360,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" @@ -1541,7 +1370,6 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.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" @@ -1550,7 +1378,6 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1: chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1567,14 +1394,12 @@ 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" @@ -1590,7 +1415,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" @@ -1610,12 +1434,10 @@ chokidar@^2.0.2: 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" @@ -1623,12 +1445,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" @@ -1638,7 +1458,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" @@ -1650,19 +1469,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@^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" @@ -1671,7 +1487,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" @@ -1680,7 +1495,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" @@ -1689,22 +1503,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" @@ -1712,7 +1522,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" @@ -1720,19 +1529,16 @@ 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" @@ -1741,125 +1547,102 @@ colors@^1.1.2: 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-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.6.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.0.tgz#1e30793e9ee5782b307e37ffa22da0eacddd84d4" - integrity sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw== 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" @@ -1867,7 +1650,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" @@ -1879,7 +1661,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" @@ -1887,7 +1668,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" @@ -1898,7 +1678,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" @@ -1910,7 +1689,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" @@ -1918,7 +1696,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" @@ -1941,7 +1718,6 @@ crypt@~0.0.1: 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" @@ -1958,77 +1734,64 @@ 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-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@*, 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.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" @@ -2039,19 +1802,16 @@ decamelize@^1.0.0, decamelize@^1.1.1: 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" @@ -2060,7 +1820,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" @@ -2071,7 +1830,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" @@ -2080,7 +1838,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" @@ -2090,7 +1847,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" @@ -2104,62 +1860,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" - 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" @@ -2167,32 +1913,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" @@ -2200,34 +1940,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" @@ -2236,7 +1970,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" @@ -2244,24 +1977,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" @@ -2270,19 +1999,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" @@ -2290,12 +2016,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.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.3" semver "^5.6.0" @@ -2303,17 +2027,14 @@ editions@^2.1.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.92" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.92.tgz#9027b5abaea400045edd652c0e4838675c814399" - integrity sha512-En051LMzMl3/asMWGZEtU808HOoVWIpmmZx1Ep8N+TT9e7z/X8RcLeBU2kLSNLGQ+5SuKELzMx+MVuTBXk6Q9w== 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" @@ -2323,7 +2044,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" @@ -2336,7 +2056,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" @@ -2346,7 +2065,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" @@ -2356,34 +2074,33 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + 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" @@ -2393,33 +2110,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.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: 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" @@ -2430,7 +2142,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" @@ -2439,7 +2150,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" @@ -2448,7 +2158,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" @@ -2457,7 +2166,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" @@ -2469,7 +2177,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" @@ -2480,7 +2187,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" @@ -2488,7 +2194,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" @@ -2498,17 +2203,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" @@ -2520,7 +2222,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" @@ -2534,7 +2235,6 @@ eslint-config-standard@^12.0.0: 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" @@ -2542,7 +2242,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" @@ -2557,7 +2256,6 @@ eslint-plugin-es@^1.3.1: 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" @@ -2603,7 +2301,6 @@ 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@^5.8.0: version "5.8.0" @@ -2651,7 +2348,6 @@ eslint@^5.8.0: espree@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" - integrity sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w== dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" @@ -2660,51 +2356,42 @@ espree@^4.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" @@ -2718,7 +2405,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" @@ -2731,7 +2417,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" @@ -2740,7 +2425,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" @@ -2757,7 +2441,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" @@ -2765,7 +2448,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" @@ -2773,7 +2455,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" @@ -2804,17 +2485,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" @@ -2829,7 +2507,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" @@ -2838,7 +2515,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" @@ -2849,7 +2525,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" @@ -2860,26 +2535,22 @@ 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-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, 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" @@ -2887,7 +2558,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" @@ -2898,7 +2568,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" @@ -2911,7 +2580,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" @@ -2924,7 +2592,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" @@ -2941,7 +2608,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" @@ -2970,7 +2636,6 @@ ethers@^4.0.7: 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" @@ -2979,7 +2644,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" @@ -2987,7 +2651,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" @@ -2995,7 +2658,6 @@ ethjs-util@^0.1.3, ethjs-util@^0.1.6: 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" @@ -3003,22 +2665,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" @@ -3026,7 +2684,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" @@ -3039,14 +2696,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" @@ -3059,14 +2714,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" @@ -3102,14 +2755,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" @@ -3121,7 +2772,6 @@ extend@~3.0.2: 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" @@ -3136,14 +2786,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" @@ -3157,77 +2805,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" @@ -3235,27 +2870,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" @@ -3266,7 +2896,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" @@ -3276,7 +2905,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" @@ -3289,7 +2917,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" @@ -3297,14 +2924,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" @@ -3314,31 +2939,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" @@ -3347,29 +2967,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" @@ -3380,7 +2995,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" @@ -3388,7 +3002,6 @@ fs-extra@^2.0.0, fs-extra@^2.1.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" @@ -3397,7 +3010,6 @@ fs-extra@^5.0.0: 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" @@ -3406,14 +3018,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" @@ -3423,7 +3033,6 @@ 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" @@ -3432,7 +3041,6 @@ fs@0.0.2: 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" @@ -3440,7 +3048,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" @@ -3450,17 +3057,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.4: 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: bn.js "4.11.8" source-map-support "0.5.9" @@ -3469,7 +3073,6 @@ ganache-cli@^6.2.4: 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" @@ -3483,12 +3086,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" @@ -3496,24 +3097,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" @@ -3521,14 +3118,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" @@ -3536,7 +3131,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" @@ -3548,7 +3142,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" @@ -3559,7 +3152,6 @@ glob@^5.0.15: 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" @@ -3571,7 +3163,6 @@ glob@^7.0.0, 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" @@ -3582,7 +3173,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" @@ -3590,17 +3180,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" @@ -3620,27 +3207,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" @@ -3651,12 +3233,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" @@ -3664,51 +3244,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" @@ -3717,7 +3288,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" @@ -3726,12 +3296,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" @@ -3739,14 +3307,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" @@ -3761,7 +3327,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" @@ -3769,7 +3334,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" @@ -3778,12 +3342,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" @@ -3792,7 +3354,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" @@ -3800,12 +3361,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" @@ -3815,12 +3374,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" @@ -3829,12 +3386,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" @@ -3846,31 +3401,26 @@ 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" @@ -3885,7 +3435,6 @@ ignore@^5.0.2: 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" @@ -3893,27 +3442,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" @@ -3921,17 +3465,14 @@ 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@^6.1.0: version "6.2.0" @@ -3954,91 +3495,76 @@ inquirer@^6.1.0: 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" @@ -4047,7 +3573,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" @@ -4056,235 +3581,194 @@ 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-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-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" - 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" @@ -4292,12 +3776,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" @@ -4317,7 +3799,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" @@ -4325,37 +3806,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", 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" @@ -4363,27 +3837,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" - 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" @@ -4395,82 +3864,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" @@ -4480,7 +3935,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" @@ -4490,7 +3944,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" @@ -4498,74 +3951,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" @@ -4575,7 +4016,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" @@ -4583,7 +4023,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" @@ -4596,7 +4035,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" @@ -4604,7 +4042,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" @@ -4615,7 +4052,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" @@ -4625,12 +4061,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" @@ -4639,7 +4073,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" @@ -4647,54 +4080,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.17.11, 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" - 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.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" @@ -4702,57 +4125,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" @@ -4769,19 +4183,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" @@ -4793,7 +4204,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" @@ -4807,7 +4217,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" @@ -4815,17 +4224,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" @@ -4839,7 +4245,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" @@ -4850,12 +4255,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" @@ -4874,7 +4277,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" @@ -4893,7 +4295,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" @@ -4901,73 +4302,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" @@ -4975,14 +4363,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" @@ -4990,14 +4376,12 @@ 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: 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" @@ -5014,7 +4398,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" @@ -5030,7 +4413,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" @@ -5047,39 +4429,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" @@ -5087,22 +4462,18 @@ 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, 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" @@ -5111,22 +4482,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.12.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.0.tgz#9d443fdb5e13a20770cc5e602eee59760a685885" - integrity sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw== 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" @@ -5143,17 +4510,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" @@ -5162,17 +4526,14 @@ 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.6.0" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" - integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== 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" @@ -5181,12 +4542,10 @@ 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" @@ -5194,7 +4553,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" @@ -5202,7 +4560,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" @@ -5231,7 +4588,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" @@ -5247,7 +4603,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" @@ -5256,14 +4611,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" @@ -5271,7 +4624,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" @@ -5281,19 +4633,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" @@ -5301,14 +4650,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" @@ -5318,12 +4665,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" @@ -5331,17 +4676,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" @@ -5350,29 +4692,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" @@ -5380,47 +4717,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@^2.1.0-rc.2: version "2.1.0-rc.2" resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.1.0-rc.2.tgz#704b7c86cc45fc82bc23ab706d767d04cf3391dc" - integrity sha512-2Yf0c4k1v0L354ZXobBn6wL207fBw+906icm4F0DYix4U+4fUMA2xgjWzVFi6zdJKZnCgBRkg+eddF8ZZY6gNA== 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" @@ -5428,7 +4758,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" @@ -5440,29 +4769,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" @@ -5471,12 +4795,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" @@ -5484,48 +4806,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.7" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.7.tgz#2473439021b57f1516c82f58be7275ad8ef1bb27" - integrity sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ== 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" @@ -5536,7 +4850,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" @@ -5546,7 +4859,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" @@ -5554,71 +4866,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.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: 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" @@ -5627,14 +4926,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" @@ -5645,126 +4942,102 @@ 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= pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== 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.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.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" @@ -5772,7 +5045,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" @@ -5784,7 +5056,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" @@ -5792,7 +5063,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" @@ -5800,22 +5070,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" @@ -5827,27 +5093,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, 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" @@ -5856,17 +5117,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.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" @@ -5875,14 +5133,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" @@ -5890,17 +5146,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" @@ -5910,7 +5163,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" @@ -5920,7 +5172,6 @@ rc@^1.2.7: react-dom@^16.2.0: version "16.6.3" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0" - integrity sha512-8ugJWRCWLGXy+7PmNh8WJz3g1TaTUt1XyoIcFN+x0Zbkoz+KKdUyx1AQLYJdbFXjuF41Nmjn5+j//rxvhFjgSQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5930,7 +5181,6 @@ react-dom@^16.2.0: react@^16.2.0: version "16.6.3" resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c" - integrity sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5940,7 +5190,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" @@ -5948,7 +5197,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" @@ -5956,7 +5204,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" @@ -5965,7 +5212,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" @@ -5974,14 +5220,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" @@ -5991,7 +5235,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.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" @@ -6004,7 +5247,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" @@ -6014,7 +5256,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" @@ -6023,34 +5264,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" @@ -6059,14 +5294,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" @@ -6078,7 +5311,6 @@ regexpp@^2.0.0, regexpp@^2.0.1: 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" @@ -6087,62 +5319,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" @@ -6152,7 +5374,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" @@ -6178,27 +5399,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-from-string@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 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" @@ -6206,41 +5422,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.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" @@ -6248,38 +5457,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" - 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" - 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.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" @@ -6287,21 +5490,18 @@ 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== rxjs@^6.1.0: version "6.3.3" @@ -6312,48 +5512,40 @@ rxjs@^6.1.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" @@ -6362,7 +5554,6 @@ scandirectory@^2.5.0: scheduler@^0.11.2: version "0.11.3" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.3.tgz#b5769b90cf8b1464f3f3cfcafe8e3cd7555a2d6b" - integrity sha512-i9X9VRRVZDd3xZw10NY5Z2cVMbdYg6gqFecfj79USv1CFN+YrJ3gIPRKf1qlY+Sxly4djoKdfx1T+m9dnRB8kQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -6370,7 +5561,6 @@ scheduler@^0.11.2: 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" @@ -6379,7 +5569,6 @@ scrypt-js@2.0.4: 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" @@ -6387,21 +5576,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" @@ -6415,29 +5601,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" @@ -6456,7 +5637,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" @@ -6466,7 +5646,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" @@ -6477,17 +5656,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" @@ -6497,7 +5673,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" @@ -6507,22 +5682,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" @@ -6530,26 +5701,22 @@ 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" @@ -6558,7 +5725,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" @@ -6567,17 +5733,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" @@ -6586,19 +5749,24 @@ 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" +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + 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" @@ -6607,14 +5775,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" @@ -6628,22 +5794,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.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" @@ -6655,7 +5817,6 @@ sol-merger@^0.1.2: solc@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.0.tgz#2deb2ae992acac3afb909f85c38d00f01dcb335e" - integrity sha512-mdLHDl9WeYrN+FIKcMc9PlPfnA9DG9ur5QpCDKcv6VC4RINAsTF4EMuXMZMKoQTvZhtLyJIVH/BZ+KU830Z8Xg== dependencies: fs-extra "^0.30.0" keccak "^1.0.2" @@ -6667,7 +5828,6 @@ solc@0.5.0: solc@^0.4.19, 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" @@ -6678,7 +5838,6 @@ solc@^0.4.19, 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" @@ -6694,7 +5853,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" @@ -6707,7 +5865,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" @@ -6716,12 +5873,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" @@ -6739,7 +5894,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" @@ -6748,17 +5902,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" @@ -6769,7 +5920,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" @@ -6777,36 +5927,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.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.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" @@ -6814,12 +5958,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" @@ -6827,29 +5969,24 @@ spdx-expression-parse@^3.0.0: spdx-license-ids@^3.0.0: 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.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.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" @@ -6864,12 +6001,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" @@ -6877,27 +6012,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" @@ -6905,7 +6035,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" @@ -6916,12 +6045,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-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" @@ -6930,15 +6057,21 @@ 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" +string-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.0.0" + 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" @@ -6947,116 +6080,104 @@ string.prototype.trim@~1.1.2: string_decoder@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== 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= 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" + 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" - 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" @@ -7081,15 +6202,22 @@ table@^5.0.2: slice-ansi "1.0.0" string-width "^2.1.1" +table@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" + dependencies: + ajv "^6.9.1" + lodash "^4.17.11" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tapable@^0.2.7: version "0.2.9" resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8" - integrity sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A== 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" @@ -7108,7 +6236,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" @@ -7121,7 +6248,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" @@ -7132,7 +6258,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" @@ -7141,7 +6266,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" @@ -7154,7 +6278,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" @@ -7162,43 +6285,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" - 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" @@ -7206,7 +6322,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" @@ -7217,36 +6332,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" @@ -7254,7 +6363,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" @@ -7264,7 +6372,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" @@ -7272,7 +6379,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" @@ -7280,27 +6386,22 @@ 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-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" @@ -7309,7 +6410,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" @@ -7320,7 +6420,6 @@ 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.2.0: version "0.2.0" @@ -7334,7 +6433,6 @@ truffle-hdwallet-provider-privkey@0.2.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" @@ -7343,7 +6441,6 @@ truffle-wallet-provider@0.0.5: truffle@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.0.tgz#2e4e2eedc5583ae38c7227585e5177d6360fbc6d" - integrity sha512-la0TJu+E59Ut62i6cGY0sugeubglDqH5w49a7IrpxZ1nnsDqv6qWB3ibiyYiCp/jr+iI0bLtcr3DKkfQjVDd+g== dependencies: app-module-path "^2.2.0" mocha "^4.1.0" @@ -7357,36 +6454,30 @@ tslib@^1.9.0: 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" @@ -7394,31 +6485,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: 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@^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" @@ -7428,7 +6514,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" @@ -7436,12 +6521,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" @@ -7450,12 +6533,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" @@ -7463,17 +6544,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" @@ -7483,22 +6561,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" @@ -7506,41 +6580,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" @@ -7548,46 +6615,38 @@ 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" - integrity sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo= dependencies: async "~0.9.0" deep-equal "~0.2.1" @@ -7599,27 +6658,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" - 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" @@ -7627,17 +6681,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" @@ -7646,14 +6697,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" @@ -7662,7 +6711,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" @@ -7676,7 +6724,6 @@ watchr@~2.4.13: 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" @@ -7685,7 +6732,6 @@ web3-bzz@1.0.0-beta.35: 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.35" @@ -7694,7 +6740,6 @@ web3-core-helpers@1.0.0-beta.35: 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.35" @@ -7705,7 +6750,6 @@ web3-core-method@1.0.0-beta.35: 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" @@ -7713,7 +6757,6 @@ web3-core-promievent@1.0.0-beta.35: 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.35" @@ -7724,7 +6767,6 @@ web3-core-requestmanager@1.0.0-beta.35: 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" @@ -7733,7 +6775,6 @@ web3-core-subscriptions@1.0.0-beta.35: 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.35" web3-core-method "1.0.0-beta.35" @@ -7743,7 +6784,6 @@ web3-core@1.0.0-beta.35: 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: bn.js "4.11.6" underscore "1.8.3" @@ -7753,7 +6793,6 @@ web3-eth-abi@1.0.0-beta.35: 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" @@ -7769,7 +6808,6 @@ web3-eth-accounts@1.0.0-beta.35: 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.35" @@ -7783,7 +6821,6 @@ web3-eth-contract@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.35" @@ -7791,7 +6828,6 @@ web3-eth-iban@1.0.0-beta.35: 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.35" web3-core-helpers "1.0.0-beta.35" @@ -7802,7 +6838,6 @@ web3-eth-personal@1.0.0-beta.35: 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.35" @@ -7820,7 +6855,6 @@ web3-eth@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" @@ -7829,7 +6863,6 @@ web3-net@1.0.0-beta.35: 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" @@ -7854,7 +6887,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" @@ -7874,7 +6906,6 @@ web3-provider-engine@^8.4.0: 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" @@ -7882,7 +6913,6 @@ web3-providers-http@1.0.0-beta.35: 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" @@ -7891,7 +6921,6 @@ web3-providers-ipc@1.0.0-beta.35: 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.35" @@ -7900,7 +6929,6 @@ web3-providers-ws@1.0.0-beta.35: 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.35" web3-core-method "1.0.0-beta.35" @@ -7910,7 +6938,6 @@ web3-shh@1.0.0-beta.35: 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" @@ -7923,7 +6950,6 @@ web3-utils@1.0.0-beta.35: 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" @@ -7934,7 +6960,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" @@ -7945,7 +6970,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" @@ -7956,7 +6980,6 @@ web3@0.20.6: 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" @@ -7969,7 +6992,6 @@ web3@1.0.0-beta.35: 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" @@ -7979,7 +7001,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" @@ -7990,7 +7011,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" @@ -8001,7 +7021,6 @@ web3@^0.20.6: 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" @@ -8009,7 +7028,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" @@ -8046,46 +7064,38 @@ 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 "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" - integrity sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4= dependencies: async "~1.0.0" colors "1.0.x" @@ -8098,7 +7108,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" @@ -8110,22 +7119,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" @@ -8133,19 +7138,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" @@ -8154,14 +7156,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" @@ -8174,19 +7174,16 @@ xhr-request@^1.0.1: xhr2-cookies@1.1.0, 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@*: 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" @@ -8200,49 +7197,40 @@ 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.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" @@ -8250,28 +7238,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@11.1.0, 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" @@ -8289,7 +7273,6 @@ yargs@11.1.0, yargs@^11.0.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" @@ -8307,7 +7290,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" @@ -8327,7 +7309,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" @@ -8346,7 +7327,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" @@ -8356,7 +7336,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 f381de38d2153c436613bc0e336eb74ed7577047 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 14 Feb 2019 15:26:12 +0530 Subject: [PATCH 109/119] cleanup --- scripts/calculateSize.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/calculateSize.js b/scripts/calculateSize.js index 92504c234..4392300bd 100644 --- a/scripts/calculateSize.js +++ b/scripts/calculateSize.js @@ -38,7 +38,6 @@ async function printSize() { size[i] ]); } - console.log(); console.log(table(dataTable)); } From ba5c75aa01a60c7d809a06820131b4eb111b323f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Feb 2019 15:32:37 +0530 Subject: [PATCH 110/119] opitmized table --- scripts/calculateSize.js | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/scripts/calculateSize.js b/scripts/calculateSize.js index 4392300bd..3f3db87f9 100644 --- a/scripts/calculateSize.js +++ b/scripts/calculateSize.js @@ -18,26 +18,17 @@ async function printSize() { let files = await readFiles(); console.log(`NOTE- Maximum size of contracts allowed to deloyed on the Ethereum mainnet is 24 KB(EIP170)`); console.log(`---- Size of the contracts ----`); - let contracts = new Array(); - let size = new Array(); + let dataTable = [['Contracts', 'Size in KB']]; files.forEach(item => { let content = JSON.parse(fs.readFileSync(`./build/contracts/${item}`).toString()).deployedBytecode; let sizeInKB = content.toString().length / 2 / 1024; - size.push(sizeInKB); if (sizeInKB > 24) - contracts.push(chalk.red(path.basename(item, ".json"))); + dataTable.push([chalk.red(path.basename(item, ".json")),chalk.red(sizeInKB)]); else if (sizeInKB > 20) - contracts.push(chalk.yellow(path.basename(item, ".json"))); + dataTable.push([chalk.yellow(path.basename(item, ".json")),chalk.yellow(sizeInKB)]); else - contracts.push(chalk.green(path.basename(item, ".json"))); + dataTable.push([chalk.green(path.basename(item, ".json")),chalk.green(sizeInKB)]); }); - let dataTable = [['Contracts', 'Size in KB']]; - for (let i = 0; i < contracts.length; i++) { - dataTable.push([ - contracts[i], - size[i] - ]); - } console.log(table(dataTable)); } From 28fdd927d4f7e92fcc57137775a4cbb503e4f3a0 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 18 Feb 2019 19:16:17 +0530 Subject: [PATCH 111/119] Migrating data to datastore (#548) * wip * wip * USDTSTO get accredited from datastore * can buy flag * Investor list moved to data store * Updated truffle * Updated changelog * Fixed modifyWhitelist tests * typo fix * Fixed gtm tests * Fixed tests * Simulation fixed * code cleanup * Removed gas limit * Added eth gas reporter * gas usage script * script fix * Added datastore tests * Added gtm tests * restored matm tests * Optimized investors key * bug fix * minor changes * Typo fix --- CHANGELOG.md | 8 +- contracts/datastore/DataStore.sol | 218 +++++++++------ contracts/datastore/DataStoreStorage.sol | 4 +- contracts/interfaces/IDataStore.sol | 8 + contracts/interfaces/ISecurityToken.sol | 5 + contracts/libraries/TokenLib.sol | 49 ++-- contracts/libraries/VersionUtils.sol | 21 +- contracts/modules/STO/CappedSTO.sol | 6 +- contracts/modules/STO/DummySTO.sol | 1 + contracts/modules/STO/PreSaleSTO.sol | 13 +- contracts/modules/STO/STO.sol | 9 + contracts/modules/STO/STOStorage.sol | 1 + contracts/modules/STO/USDTieredSTO.sol | 71 ++--- .../TransferManager/CountTransferManager.sol | 2 +- .../GeneralTransferManager.sol | 254 ++++++++++-------- .../storage/GeneralTransferManagerStorage.sol | 34 ++- contracts/storage/USDTieredSTOStorage.sol | 19 +- contracts/tokens/SecurityToken.sol | 56 ++-- docs/investor_flags.md | 23 ++ package.json | 4 +- scripts/gasUsage.sh | 8 + test/b_capped_sto.js | 16 +- test/c_checkpoints.js | 12 +- test/d_count_transfer_manager.js | 36 +-- test/e_erc20_dividends.js | 16 +- test/f_ether_dividends.js | 20 +- test/h_general_transfer_manager.js | 111 +++----- test/helpers/signData.js | 10 +- test/i_Issuance.js | 6 +- test/j_manual_approval_transfer_manager.js | 12 +- test/l_percentage_transfer_manager.js | 12 +- test/m_presale_sto.js | 6 +- test/o_security_token.js | 46 ++-- test/p_usd_tiered_sto.js | 108 ++------ test/q_usd_tiered_sto_sim.js | 17 +- test/r_concurrent_STO.js | 2 +- test/v_tracked_redemptions.js | 8 +- test/w_lockup_transfer_manager.js | 12 +- test/x_scheduled_checkpoints.js | 12 +- test/y_volume_restriction_tm.js | 8 +- test/z_blacklist_transfer_manager.js | 20 +- ...zer_volumn_restriction_transfer_manager.js | 4 +- test/z_general_permission_manager_fuzzer.js | 12 +- test/z_vesting_escrow_wallet.js | 8 +- test/za_datastore.js | 8 + test/zb_signed_transfer_manager.js | 4 +- truffle-config-gas.js | 81 ++++++ yarn.lock | 223 ++++++++++++++- 48 files changed, 943 insertions(+), 701 deletions(-) create mode 100644 docs/investor_flags.md create mode 100755 scripts/gasUsage.sh create mode 100644 truffle-config-gas.js diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e428e11..94a8c2ce4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ All notable changes to this project will be documented in this file. * Fixed `addModule` function to be backwards compatible and call the new `addModuleWithLabel` function with an empty label. * Fixed event `ModuleAdded` to also emit `_label`. * Fixed function `getModule` to also return the respective module label. +* Added datastore that is used to store data like investor list that is shared among modules. +* `getInvestorCount()` now returns length of investor array that is everyone who ever held some st or has kyc data attached. +* `holderCount()` returns the number of current st holders. +* Added flags for Investors. Accredited and canbuyfromsto are now flags ## STR * Introduce new contract `STRGetter.sol`. It only contains the getter functions of the STR. @@ -19,7 +23,9 @@ All notable changes to this project will be documented in this file. * Removed `_polyToken` parameter from `initialize` function in `SecurityTokenRegistry`. ## GeneralTransferManager -* Add `_isAccredited` variable in the `modifyWhitelist()` function of the GeneralTransferManager. +* `modifyWhitelist()` function renamed to `modifyKYCData()`. +* Added functions to modify and get flags +* `canBuyFromSto` is now `canNotBuyFromSto` and it is the flag `1` ## Generalize * Removed `_polyAddress` parameter from constructors of all modules and module factories. diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 3c68aac97..958f8c51d 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -12,26 +12,24 @@ contract DataStore is DataStoreStorage, IDataStore { //NB To modify a specific element of an array, First push a new element to the array and then delete the old element. //Whenver an element is deleted from an Array, last element of that array is moved to the index of deleted element. //Delegate with MANAGEDATA permission can modify data. - event SecurityTokenChanged(address indexed _oldSecurityToken, address indexed _newSecurityToken); - modifier onlyAuthorized() { - bool isOwner = msg.sender == IOwnable(address(securityToken)).owner(); - require(isOwner || - securityToken.isModule(msg.sender, DATA_KEY) || - securityToken.checkPermission(msg.sender, address(this), MANAGEDATA), + function _isAuthorized() internal view { + require(msg.sender == address(securityToken) || + msg.sender == IOwnable(address(securityToken)).owner() || + securityToken.checkPermission(msg.sender, address(this), MANAGEDATA) || + securityToken.isModule(msg.sender, DATA_KEY), "Unauthorized" ); - _; } modifier validKey(bytes32 _key) { - require(_key != bytes32(0), "Missing key"); + require(_key != bytes32(0), "bad key"); _; } modifier validArrayLength(uint256 _keyLength, uint256 _dataLength) { - require(_keyLength == _dataLength, "Array length mismatch"); + require(_keyLength == _dataLength, "bad length"); _; } @@ -55,27 +53,33 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _key Unique key to identify the data * @param _data Data to be stored against the key */ - function setUint256(bytes32 _key, uint256 _data) external onlyAuthorized { - _setData(_key, _data); + function setUint256(bytes32 _key, uint256 _data) external { + _isAuthorized(); + _setData(_key, _data, false); } - function setBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { - _setData(_key, _data); + function setBytes32(bytes32 _key, bytes32 _data) external { + _isAuthorized(); + _setData(_key, _data, false); } - function setAddress(bytes32 _key, address _data) external onlyAuthorized { - _setData(_key, _data); + function setAddress(bytes32 _key, address _data) external { + _isAuthorized(); + _setData(_key, _data, false); } - function setString(bytes32 _key, string calldata _data) external onlyAuthorized { - _setData(_key, _data); + function setBool(bytes32 _key, bool _data) external { + _isAuthorized(); + _setData(_key, _data, false); } - function setBytes(bytes32 _key, bytes calldata _data) external onlyAuthorized { + function setString(bytes32 _key, string calldata _data) external { + _isAuthorized(); _setData(_key, _data); } - function setBool(bytes32 _key, bool _data) external onlyAuthorized { + function setBytes(bytes32 _key, bytes calldata _data) external { + _isAuthorized(); _setData(_key, _data); } @@ -84,19 +88,23 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _key Unique key to identify the array * @param _data Array to be stored against the key */ - function setUint256Array(bytes32 _key, uint256[] calldata _data) external onlyAuthorized { + function setUint256Array(bytes32 _key, uint256[] calldata _data) external { + _isAuthorized(); _setData(_key, _data); } - function setBytes32Array(bytes32 _key, bytes32[] calldata _data) external onlyAuthorized { + function setBytes32Array(bytes32 _key, bytes32[] calldata _data) external { + _isAuthorized(); _setData(_key, _data); } - function setAddressArray(bytes32 _key, address[] calldata _data) external onlyAuthorized { + function setAddressArray(bytes32 _key, address[] calldata _data) external { + _isAuthorized(); _setData(_key, _data); } - function setBoolArray(bytes32 _key, bool[] calldata _data) external onlyAuthorized { + function setBoolArray(bytes32 _key, bool[] calldata _data) external { + _isAuthorized(); _setData(_key, _data); } @@ -105,20 +113,24 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _key Unique key to identify the array * @param _data Element to push into the array */ - function insertUint256(bytes32 _key, uint256 _data) external onlyAuthorized { - _insertData(_key, _data); + function insertUint256(bytes32 _key, uint256 _data) external { + _isAuthorized(); + _setData(_key, _data, true); } - function insertBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { - _insertData(_key, _data); + function insertBytes32(bytes32 _key, bytes32 _data) external { + _isAuthorized(); + _setData(_key, _data, true); } - function insertAddress(bytes32 _key, address _data) external onlyAuthorized { - _insertData(_key, _data); + function insertAddress(bytes32 _key, address _data) external { + _isAuthorized(); + _setData(_key, _data, true); } - function insertBool(bytes32 _key, bool _data) external onlyAuthorized { - _insertData(_key, _data); + function insertBool(bytes32 _key, bool _data) external { + _isAuthorized(); + _setData(_key, _data, true); } /** @@ -127,19 +139,23 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _key Unique key to identify the array * @param _index Index of the element to delete */ - function deleteUint256(bytes32 _key, uint256 _index) external onlyAuthorized { + function deleteUint256(bytes32 _key, uint256 _index) external { + _isAuthorized(); _deleteUint(_key, _index); } - function deleteBytes32(bytes32 _key, uint256 _index) external onlyAuthorized { + function deleteBytes32(bytes32 _key, uint256 _index) external { + _isAuthorized(); _deleteBytes32(_key, _index); } - function deleteAddress(bytes32 _key, uint256 _index) external onlyAuthorized { + function deleteAddress(bytes32 _key, uint256 _index) external { + _isAuthorized(); _deleteAddress(_key, _index); } - function deleteBool(bytes32 _key, uint256 _index) external onlyAuthorized { + function deleteBool(bytes32 _key, uint256 _index) external { + _isAuthorized(); _deleteBool(_key, _index); } @@ -148,27 +164,31 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _keys Array of keys to identify the data * @param _data Array of data to be stored against the respective keys */ - function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function setUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _setData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], false); } } - function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function setBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _setData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], false); } } - function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function setAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _setData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], false); } } - function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function setBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _setData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], false); } } @@ -177,27 +197,31 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _keys Array of keys to identify the data * @param _data Array of data to be inserted in arrays of the respective keys */ - function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function insertUint256Multi(bytes32[] calldata _keys, uint256[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _insertData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], true); } } - function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function insertBytes32Multi(bytes32[] calldata _keys, bytes32[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _insertData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], true); } } - function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function insertAddressMulti(bytes32[] calldata _keys, address[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _insertData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], true); } } - function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external onlyAuthorized validArrayLength(_keys.length, _data.length) { + function insertBoolMulti(bytes32[] calldata _keys, bool[] calldata _data) external validArrayLength(_keys.length, _data.length) { + _isAuthorized(); for (uint256 i = 0; i < _keys.length; i++) { - _insertData(_keys[i], _data[i]); + _setData(_keys[i], _data[i], true); } } @@ -273,16 +297,60 @@ contract DataStore is DataStoreStorage, IDataStore { return boolArrayData[_key][_index]; } - function _setData(bytes32 _key, uint256 _data) internal validKey(_key) { - uintData[_key] = _data; + function getUint256ArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(uint256[] memory array) { + uint256 size = _endIndex - _startIndex + 1; + array = new uint256[](size); + for(uint256 i; i < size; i++) + array[i] = uintArrayData[_key][i + _startIndex]; + } + + function getBytes32ArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(bytes32[] memory array) { + uint256 size = _endIndex - _startIndex + 1; + array = new bytes32[](size); + for(uint256 i; i < size; i++) + array[i] = bytes32ArrayData[_key][i + _startIndex]; + } + + function getAddressArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(address[] memory array) { + uint256 size = _endIndex - _startIndex + 1; + array = new address[](size); + for(uint256 i; i < size; i++) + array[i] = addressArrayData[_key][i + _startIndex]; + } + + function getBoolArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(bool[] memory array) { + uint256 size = _endIndex - _startIndex + 1; + array = new bool[](size); + for(uint256 i; i < size; i++) + array[i] = boolArrayData[_key][i + _startIndex]; + } + + function _setData(bytes32 _key, uint256 _data, bool _insert) internal validKey(_key) { + if (_insert) + uintArrayData[_key].push(_data); + else + uintData[_key] = _data; + } + + function _setData(bytes32 _key, bytes32 _data, bool _insert) internal validKey(_key) { + if (_insert) + bytes32ArrayData[_key].push(_data); + else + bytes32Data[_key] = _data; } - function _setData(bytes32 _key, bytes32 _data) internal validKey(_key) { - bytes32Data[_key] = _data; + function _setData(bytes32 _key, address _data, bool _insert) internal validKey(_key) { + if (_insert) + addressArrayData[_key].push(_data); + else + addressData[_key] = _data; } - function _setData(bytes32 _key, address _data) internal validKey(_key) { - addressData[_key] = _data; + function _setData(bytes32 _key, bool _data, bool _insert) internal validKey(_key) { + if (_insert) + boolArrayData[_key].push(_data); + else + boolData[_key] = _data; } function _setData(bytes32 _key, string memory _data) internal validKey(_key) { @@ -293,10 +361,6 @@ contract DataStore is DataStoreStorage, IDataStore { bytesData[_key] = _data; } - function _setData(bytes32 _key, bool _data) internal validKey(_key) { - boolData[_key] = _data; - } - function _setData(bytes32 _key, uint256[] memory _data) internal validKey(_key) { uintArrayData[_key] = _data; } @@ -313,51 +377,27 @@ contract DataStore is DataStoreStorage, IDataStore { boolArrayData[_key] = _data; } - function _insertData(bytes32 _key, uint256 _data) internal validKey(_key) { - uintArrayData[_key].push(_data); - } - - function _insertData(bytes32 _key, bytes32 _data) internal validKey(_key) { - bytes32ArrayData[_key].push(_data); - } - - function _insertData(bytes32 _key, address _data) internal validKey(_key) { - addressArrayData[_key].push(_data); - } - - function _insertData(bytes32 _key, bool _data) internal validKey(_key) { - boolArrayData[_key].push(_data); - } - function _deleteUint(bytes32 _key, uint256 _index) internal validKey(_key) { require(uintArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(uintArrayData[_key].length - 1 != _index) { - uintArrayData[_key][_index] = uintArrayData[_key][uintArrayData[_key].length - 1]; - } + uintArrayData[_key][_index] = uintArrayData[_key][uintArrayData[_key].length - 1]; uintArrayData[_key].length--; } function _deleteBytes32(bytes32 _key, uint256 _index) internal validKey(_key) { require(bytes32ArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(bytes32ArrayData[_key].length - 1 != _index) { - bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][bytes32ArrayData[_key].length - 1]; - } + bytes32ArrayData[_key][_index] = bytes32ArrayData[_key][bytes32ArrayData[_key].length - 1]; bytes32ArrayData[_key].length--; } function _deleteAddress(bytes32 _key, uint256 _index) internal validKey(_key) { require(addressArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(addressArrayData[_key].length - 1 != _index) { - addressArrayData[_key][_index] = addressArrayData[_key][addressArrayData[_key].length - 1]; - } + addressArrayData[_key][_index] = addressArrayData[_key][addressArrayData[_key].length - 1]; addressArrayData[_key].length--; } function _deleteBool(bytes32 _key, uint256 _index) internal validKey(_key) { require(boolArrayData[_key].length > _index, "Invalid Index"); //Also prevents undeflow - if(boolArrayData[_key].length - 1 != _index) { - boolArrayData[_key][_index] = boolArrayData[_key][boolArrayData[_key].length - 1]; - } + boolArrayData[_key][_index] = boolArrayData[_key][boolArrayData[_key].length - 1]; boolArrayData[_key].length--; } } diff --git a/contracts/datastore/DataStoreStorage.sol b/contracts/datastore/DataStoreStorage.sol index 9d724f070..64423f39d 100644 --- a/contracts/datastore/DataStoreStorage.sol +++ b/contracts/datastore/DataStoreStorage.sol @@ -16,6 +16,6 @@ contract DataStoreStorage { mapping (bytes32 => address[]) internal addressArrayData; mapping (bytes32 => bool[]) internal boolArrayData; - uint8 constant DATA_KEY = 6; - bytes32 public constant MANAGEDATA = "MANAGEDATA"; + uint8 internal constant DATA_KEY = 6; + bytes32 internal constant MANAGEDATA = "MANAGEDATA"; } diff --git a/contracts/interfaces/IDataStore.sol b/contracts/interfaces/IDataStore.sol index bb1aa5aa4..33df6b934 100644 --- a/contracts/interfaces/IDataStore.sol +++ b/contracts/interfaces/IDataStore.sol @@ -125,4 +125,12 @@ interface IDataStore { function getAddressArrayElement(bytes32 _key, uint256 _index) external view returns(address); function getBoolArrayElement(bytes32 _key, uint256 _index) external view returns(bool); + + function getUint256ArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(uint256[] memory); + + function getBytes32ArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(bytes32[] memory); + + function getAddressArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(address[] memory); + + function getBoolArrayElements(bytes32 _key, uint256 _startIndex, uint256 _endIndex) external view returns(bool[] memory); } diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index c1671db53..af0fb6a0c 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -316,6 +316,11 @@ interface ISecurityToken { */ function getInvestorCount() external view returns(uint256); + /** + * @notice Gets the holder count (investors with non zero balance) + */ + function holderCount() external view returns(uint256); + /** * @notice Overloaded version of the transfer function * @param _to receiver of transfer diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 239c57941..bbbf78bb9 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -2,10 +2,14 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../interfaces/IPoly.sol"; +import "../interfaces/IDataStore.sol"; library TokenLib { using SafeMath for uint256; + bytes32 internal constant WHITELIST = "WHITELIST"; + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) + // Struct for module data struct ModuleData { bytes32 name; @@ -24,15 +28,6 @@ library TokenLib { uint256 value; } - struct InvestorDataStorage { - // List of investors who have ever held a non-zero token balance - mapping(address => bool) investorListed; - // List of token holders - address[] investors; - // Total number of non-zero token holders - uint256 investorCount; - } - // Emit when Module is archived from the SecurityToken event ModuleArchived(uint8[] _types, address _module); // Emit when Module is unarchived from the SecurityToken @@ -217,40 +212,54 @@ library TokenLib { /** * @notice Keeps track of the number of non-zero token holders - * @param _investorData Date releated to investor metrics + * @param _holderCount Number of current token holders * @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 _dataStore address of data store */ function adjustInvestorCount( - InvestorDataStorage storage _investorData, + uint256 _holderCount, address _from, address _to, uint256 _value, uint256 _balanceTo, - uint256 _balanceFrom + uint256 _balanceFrom, + address _dataStore ) public + returns(uint256) { if ((_value == 0) || (_from == _to)) { - return; + return _holderCount; } // Check whether receiver is a new token holder if ((_balanceTo == 0) && (_to != address(0))) { - _investorData.investorCount = (_investorData.investorCount).add(1); + _holderCount = _holderCount.add(1); + IDataStore dataStore = IDataStore(_dataStore); + if (!_isExistingInvestor(_to, dataStore)) { + dataStore.insertAddress(INVESTORSKEY, _to); + //KYC data can not be present if added is false and hence we can set packed KYC as uint256(1) to set added as true + dataStore.setUint256(_getKey(WHITELIST, _to), uint256(1)); + } } // Check whether sender is moving all of their tokens if (_value == _balanceFrom) { - _investorData.investorCount = (_investorData.investorCount).sub(1); - } - //Also adjust investor list - if (!_investorData.investorListed[_to] && (_to != address(0))) { - _investorData.investors.push(_to); - _investorData.investorListed[_to] = true; + _holderCount = _holderCount.sub(1); } + return _holderCount; + } + + function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } + function _isExistingInvestor(address _investor, IDataStore dataStore) internal view returns(bool) { + uint256 data = dataStore.getUint256(_getKey(WHITELIST, _investor)); + //extracts `added` from packed `whitelistData` + return uint8(data) == 0 ? false : true; + } } diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 8375cde68..e878389bb 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -110,21 +110,22 @@ library VersionUtils { /** * @notice Used to packed the KYC data */ - function packKYC(uint64 _a, uint64 _b, uint64 _c, uint8 _d, uint8 _e, uint8 _f) internal pure returns(uint256) { - return (uint256(_a) << 152) | (uint256(_b) << 88) | (uint256(_c) << 24) | (uint256(_d) << 16) | (uint256(_e) << 8) | uint256(_f); + function packKYC(uint64 _a, uint64 _b, uint64 _c, uint8 _d) internal pure returns(uint256) { + // this function packs 3 uint64 and a uint8 together in a uint256 to save storage cost + // a is rotated left by 136 bits, b is rotated left by 72 bits and c is rotated left by 8 bits. + // rotation pads empty bits with zeroes so now we can safely do a bitwise OR operation to pack + // all the variables together. + return (uint256(_a) << 136) | (uint256(_b) << 72) | (uint256(_c) << 8) | uint256(_d); } /** * @notice Used to convert packed data into KYC data * @param _packedVersion Packed data */ - function unpackKYC(uint256 _packedVersion) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 canBuy, uint8 added, uint8 accredited) { - fromTime = uint64(_packedVersion >> 152); - toTime = uint64(_packedVersion >> 88); - expiryTime = uint64(_packedVersion >> 24); - canBuy = uint8(_packedVersion >> 16); - added = uint8(_packedVersion >> 8); - accredited = uint8(_packedVersion); + function unpackKYC(uint256 _packedVersion) internal pure returns(uint64 fromTime, uint64 toTime, uint64 expiryTime, uint8 added) { + fromTime = uint64(_packedVersion >> 136); + toTime = uint64(_packedVersion >> 72); + expiryTime = uint64(_packedVersion >> 8); + added = uint8(_packedVersion); } - } diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 8286da28f..4cec5d9c9 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -208,10 +208,10 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { Observe state and use revert statements to undo rollback when valid conditions are not met. */ function _postValidatePurchase( - address, /*_beneficiary*/ + address _beneficiary, uint256 /*_investedAmount*/ - ) internal pure { - // optional override + ) internal view { + require(_canBuy(_beneficiary), "Unauthorized"); } /** diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index 8b1a9101d..f562be892 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -47,6 +47,7 @@ contract DummySTO is DummySTOStorage, STO { function generateTokens(address _investor, uint256 _amount) public withPerm(ADMIN) { require(!paused, "Should not be paused"); require(_amount > 0, "Amount should be greater than 0"); + require(_canBuy(_investor), "Unauthorized"); ISecurityToken(securityToken).mint(_investor, _amount); if (investors[_investor] == 0) { investorCount = investorCount + 1; diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 824b808fc..98fd033f3 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -71,13 +71,14 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { uint256 _amount, uint256 _etherContributed, uint256 _polyContributed - ) - public - withPerm(PRE_SALE_ADMIN) + ) + public + withPerm(PRE_SALE_ADMIN) { /*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"); + require(_canBuy(_investor), "Unauthorized"); ISecurityToken(securityToken).mint(_investor, _amount); if (investors[_investor] == uint256(0)) { investorCount = investorCount.add(1); @@ -101,9 +102,9 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { uint256[] memory _amounts, uint256[] memory _etherContributed, uint256[] memory _polyContributed - ) - public - withPerm(PRE_SALE_ADMIN) + ) + public + withPerm(PRE_SALE_ADMIN) { require(_investors.length == _amounts.length, "Mis-match in length of the arrays"); require(_etherContributed.length == _polyContributed.length, "Mis-match in length of the arrays"); diff --git a/contracts/modules/STO/STO.sol b/contracts/modules/STO/STO.sol index d3f28c5fd..ae69238fd 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -70,4 +70,13 @@ contract STO is ISTO, STOStorage, Module, Pausable { emit SetFundRaiseTypes(_fundRaiseTypes); } + function _canBuy(address _investor) internal view returns(bool) { + IDataStore dataStore = IDataStore(getDataStore()); + uint256 flags = dataStore.getUint256(_getKey(INVESTORFLAGS, _investor)); + return(flags & (uint256(1) << 1) == 0); + } + + function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1, _key2))); + } } diff --git a/contracts/modules/STO/STOStorage.sol b/contracts/modules/STO/STOStorage.sol index 96793d6d5..87ae2c3e0 100644 --- a/contracts/modules/STO/STOStorage.sol +++ b/contracts/modules/STO/STOStorage.sol @@ -5,6 +5,7 @@ pragma solidity ^0.5.0; */ contract STOStorage { + bytes32 internal constant INVESTORFLAGS = "INVESTORFLAGS"; mapping (uint8 => bool) public fundRaiseTypes; mapping (uint8 => uint256) public fundsRaised; diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 18231229c..6de21c48d 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -199,7 +199,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { internal { require( - _tokensPerTierTotal.length > 0 && + _tokensPerTierTotal.length > 0 && _ratePerTier.length == _tokensPerTierTotal.length && _ratePerTierDiscountPoly.length == _tokensPerTierTotal.length && _tokensPerTierDiscountPoly.length == _tokensPerTierTotal.length, @@ -272,24 +272,6 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { totalTokensSold = tempSold; } - /** - * @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[] memory _investors, bool[] memory _accredited) public onlyOwner { - require(_investors.length == _accredited.length, "Array length mismatch"); - for (uint256 i = 0; i < _investors.length; 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]); - } - } - /** * @notice Modifies the list of overrides for non-accredited limits in USD * @param _investors Array of investor addresses to modify @@ -299,34 +281,26 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { //nonAccreditedLimitUSDOverride require(_investors.length == _nonAccreditedLimit.length, "Array length mismatch"); for (uint256 i = 0; i < _investors.length; i++) { - investors[_investors[i]].nonAccreditedLimitUSDOverride = _nonAccreditedLimit[i]; - _addToInvestorsList(_investors[i]); + nonAccreditedLimitUSDOverride[_investors[i]] = _nonAccreditedLimit[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 + * @return investors list of all configured investors + * @return accredited whether investor is accredited + * @return override any USD overrides for non-accredited limits for the investor */ - function getAccreditedData() external view returns (address[] memory, bool[] memory, uint256[] memory) { - 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; + function getAccreditedData() external view returns (address[] memory investors, bool[] memory accredited, uint256[] memory overrides) { + IDataStore dataStore = IDataStore(getDataStore()); + investors = dataStore.getAddressArray(INVESTORSKEY); + accredited = new bool[](investors.length); + overrides = new uint256[](investors.length); + for (uint256 i = 0; i < investors.length; i++) { + accredited[i] = _getIsAccredited(investors[i], dataStore); + overrides[i] = nonAccreditedLimitUSDOverride[investors[i]]; } - return (investorsList, accrediteds, nonAccreditedLimitUSDOverrides); } /** @@ -443,6 +417,8 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { require(_beneficiary == msg.sender, "Beneficiary != funder"); } + require(_canBuy(_beneficiary), "Unauthorized"); + uint256 originalUSD = DecimalMath.mul(_rate, _investmentValue); uint256 allowedUSD = _buyTokensChecks(_beneficiary, _investmentValue, originalUSD); @@ -489,8 +465,8 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { require(investedUSD.add(investorInvestedUSD[_beneficiary]) >= minimumInvestmentUSD, "Investment < min"); netInvestedUSD = investedUSD; // Check for non-accredited cap - if (investors[_beneficiary].accredited == uint8(0)) { - uint256 investorLimitUSD = (investors[_beneficiary].nonAccreditedLimitUSDOverride == 0) ? nonAccreditedLimitUSD : investors[_beneficiary].nonAccreditedLimitUSDOverride; + if (!_isAccredited(_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]); @@ -568,6 +544,17 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { } } + function _isAccredited(address _investor) internal view returns(bool) { + IDataStore dataStore = IDataStore(getDataStore()); + return _getIsAccredited(_investor, dataStore); + } + + function _getIsAccredited(address _investor, IDataStore dataStore) internal view returns(bool) { + uint256 flags = dataStore.getUint256(_getKey(INVESTORFLAGS, _investor)); + uint256 flag = flags & uint256(1); //isAccredited is flag 0 so we don't need to bit shift flags. + return flag > 0 ? true : false; + } + ///////////// // Getters // ///////////// @@ -577,7 +564,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { * @return bool Whether the STO is accepting investments */ function isOpen() public view returns(bool) { - /*solium-disable-next-line security/no-block-members*/ + /*solium-disable-next-line security/no-block-members*/ if (isFinalized || now < startTime || now >= endTime || capReached()) return false; return true; diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index b598505f0..381584389 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -34,7 +34,7 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { returns(Result) { if (!paused) { - if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { + if (maxHolderCount < ISecurityToken(securityToken).holderCount()) { // Allow transfers to existing maxHolders if (ISecurityToken(securityToken).balanceOf(_to) != 0 || ISecurityToken(securityToken).balanceOf(_from) == _amount) { return Result.NA; diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 0139291ef..981830437 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -34,15 +34,19 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage // 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( + event ModifyKYCData( address indexed _investor, uint256 _dateAdded, address indexed _addedBy, uint256 _fromTime, uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO, - bool _isAccredited + uint256 _expiryTime + ); + + event ModifyInvestorFlag( + address indexed _investor, + uint8 indexed _flag, + bool _value ); /** @@ -158,7 +162,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint64 fromExpiry; uint64 toExpiry; uint64 toTime; - uint8 canBuyFromSTO; if (allowAllTransfers) { //All transfers allowed, regardless of whitelist return Result.VALID; @@ -167,7 +170,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return Result.VALID; } - (fromTime, fromExpiry, canBuyFromSTO, toTime, toExpiry) = _getValuesForTransfer(_from, _to); + (fromTime, fromExpiry, toTime, toExpiry) = _getValuesForTransfer(_from, _to); if (allowAllWhitelistTransfers) { //Anyone on the whitelist can transfer, regardless of time @@ -176,10 +179,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage // Using the local variables to avoid the stack too deep error (fromTime, toTime) = _adjustTimes(fromTime, toTime); if (_from == issuanceAddress) { - // Possible STO transaction, but investor not allowed to purchased from STO - if ((canBuyFromSTO == uint8(0)) && _isSTOAttached()) { - return Result.NA; - } // if allowAllWhitelistIssuances is true, so time stamp ignored if (allowAllWhitelistIssuances) { return _validExpiry(toExpiry) ? Result.VALID : Result.NA; @@ -197,84 +196,120 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage } /** - * @notice Adds or removes addresses from the whitelist. + * @notice Add or remove KYC info of an investor. * @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. - * @param _isAccredited is used to differentiate whether the investor is Accredited or not. */ - function modifyWhitelist( + function modifyKYCData( address _investor, uint256 _fromTime, uint256 _toTime, - uint256 _expiryTime, - bool _canBuyFromSTO, - bool _isAccredited + uint256 _expiryTime ) public withPerm(WHITELIST) { - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); + _modifyKYCData(_investor, _fromTime, _toTime, _expiryTime); + } + + function _modifyKYCData(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime) internal { + require(_investor != address(0), "Invalid investor"); + IDataStore dataStore = IDataStore(getDataStore()); + if (!_isExistingInvestor(_investor, dataStore)) { + dataStore.insertAddress(INVESTORSKEY, _investor); + } + uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), uint8(1)); + dataStore.setUint256(_getKey(WHITELIST, _investor), _data); + emit ModifyKYCData(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime); } /** - * @notice Adds or removes addresses from the whitelist. - * @param _investor is the address to whitelist + * @notice Add or remove KYC info of an investor. + * @param _investors 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. - * @param _isAccredited is used to differentiate whether the investor is Accredited or not. */ - function _modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO, bool _isAccredited) internal { + function modifyKYCDataMulti( + address[] memory _investors, + uint256[] memory _fromTime, + uint256[] memory _toTime, + uint256[] memory _expiryTime + ) + public + withPerm(WHITELIST) + { + require( + _investors.length == _fromTime.length && + _fromTime.length == _toTime.length && + _toTime.length == _expiryTime.length, + "Mismatched input lengths" + ); + for (uint256 i = 0; i < _investors.length; i++) { + _modifyKYCData(_investors[i], _fromTime[i], _toTime[i], _expiryTime[i]); + } + } + + /** + * @notice Used to modify investor Flag. + * @dev Flags are properties about investors that can be true or false like isAccredited + * @param _investor is the address of the investor. + * @param _flag index of flag to change. flag is used to know specifics about investor like isAccredited. + * @param _value value of the flag. a flag can be true or false. + */ + function modifyInvestorFlag( + address _investor, + uint8 _flag, + bool _value + ) + public + withPerm(WHITELIST) + { + _modifyInvestorFlag(_investor, _flag, _value); + } + + + function _modifyInvestorFlag(address _investor, uint8 _flag, bool _value) internal { require(_investor != address(0), "Invalid investor"); - uint8 added; - uint8 canBuyFromSTO; - uint8 isAccredited; IDataStore dataStore = IDataStore(getDataStore()); - added = _getAddedValue(_investor, dataStore); - if (added == uint8(0)) { - investors.push(_investor); + if (!_isExistingInvestor(_investor, dataStore)) { + dataStore.insertAddress(INVESTORSKEY, _investor); + //KYC data can not be present if added is false and hence we can set packed KYC as uint256(1) to set added as true + dataStore.setUint256(_getKey(WHITELIST, _investor), uint256(1)); } - canBuyFromSTO = _canBuyFromSTO ? 1 : 0; - isAccredited = _isAccredited ? 1 : 0; - uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), canBuyFromSTO, uint8(1), isAccredited); - dataStore.setUint256(_getKey(WHITELIST, _investor), _data); - emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); + //NB Flags are packed together in a uint256 to save gas. We can have a maximum of 256 flags. + uint256 flags = dataStore.getUint256(_getKey(INVESTORFLAGS, _investor)); + if (_value) + flags = flags | (ONE << _flag); + else + flags = flags & ~(ONE << _flag); + dataStore.setUint256(_getKey(INVESTORFLAGS, _investor), flags); + emit ModifyInvestorFlag(_investor, _flag, _value); } /** - * @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 _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. - * @param _isAccredited An array of boolean values to differentiate whether the investor is Accredited or not. + * @notice Used to modify investor data. + * @param _investors List of the addresses to modify data about. + * @param _flag index of flag to change. flag is used to know specifics about investor like isAccredited. + * @param _value value of the flag. a flag can be true or false. */ - function modifyWhitelistMulti( + function modifyInvestorFlagMulti( address[] memory _investors, - uint256[] memory _fromTimes, - uint256[] memory _toTimes, - uint256[] memory _expiryTimes, - bool[] memory _canBuyFromSTO, - bool[] memory _isAccredited + uint8[] memory _flag, + bool[] memory _value ) public withPerm(WHITELIST) { require( - _investors.length == _fromTimes.length && - _fromTimes.length == _toTimes.length && - _toTimes.length == _expiryTimes.length && - _canBuyFromSTO.length == _toTimes.length && - _canBuyFromSTO.length == _isAccredited.length, + _investors.length == _flag.length && + _flag.length == _value.length, "Mismatched input lengths" ); for (uint256 i = 0; i < _investors.length; i++) { - _modifyWhitelist(_investors[i], _fromTimes[i], _toTimes[i], _expiryTimes[i], _canBuyFromSTO[i], _isAccredited[i]); + _modifyInvestorFlag(_investors[i], _flag[i], _value[i]); } } @@ -284,20 +319,16 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @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. - * @param _isAccredited is used to differentiate whether the investor is Accredited 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 _signature issuer signature */ - function modifyWhitelistSigned( + function modifyKYCDataSigned( address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, - bool _canBuyFromSTO, - bool _isAccredited, uint256 _validFrom, uint256 _validTo, uint256 _nonce, @@ -312,10 +343,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( - abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited, _validFrom, _validTo, _nonce) + abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _validFrom, _validTo, _nonce) ); _checkSig(hash, _signature); - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); + _modifyKYCData(_investor, _fromTime, _toTime, _expiryTime); } /** @@ -344,14 +375,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return (_lockTime <= uint64(now)); /*solium-disable-line security/no-block-members*/ } - /** - * @notice Internal function use to know whether the STO is attached or not - */ - function _isSTOAttached() internal view returns(bool) { - bool attached = ISecurityToken(securityToken).getModulesByType(3).length > 0; - return attached; - } - /** * @notice Internal function to adjust times using default values */ @@ -371,87 +394,104 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function _getValues(address _investor, IDataStore dataStore) internal view returns( + function _getKYCValues(address _investor, IDataStore dataStore) internal view returns( uint64 fromTime, uint64 toTime, uint64 expiryTime, - uint8 canBuyFromSTO, - uint8 added, - uint8 isAccredited + uint8 added ) { - uint256 _whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); - (fromTime, toTime, expiryTime, canBuyFromSTO, added, isAccredited) = VersionUtils.unpackKYC(_whitelistData); + uint256 data = dataStore.getUint256(_getKey(WHITELIST, _investor)); + (fromTime, toTime, expiryTime, added) = VersionUtils.unpackKYC(data); } - function _getAddedValue(address _investor, IDataStore dataStore) internal view returns(uint8) { - uint256 _whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); + function _isExistingInvestor(address _investor, IDataStore dataStore) internal view returns(bool) { + uint256 data = dataStore.getUint256(_getKey(WHITELIST, _investor)); //extracts `added` from packed `_whitelistData` - return uint8(_whitelistData >> 8); + return uint8(data) == 0 ? false : true; } - function _getValuesForTransfer(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint8 canBuyFromSTO, uint64 toTime, uint64 toExpiry) { + function _getValuesForTransfer(address _from, address _to) internal view returns(uint64 fromTime, uint64 fromExpiry, uint64 toTime, uint64 toExpiry) { IDataStore dataStore = IDataStore(getDataStore()); - (fromTime,, fromExpiry,,,) = _getValues(_from, dataStore); - (, toTime, toExpiry, canBuyFromSTO,,) = _getValues(_to, dataStore); + (fromTime, , fromExpiry, ) = _getKYCValues(_from, dataStore); + (, toTime, toExpiry, ) = _getKYCValues(_to, dataStore); } /** * @dev Returns list of all investors */ - function getInvestors() public view returns(address[] memory) { - return investors; + function getAllInvestors() public view returns(address[] memory investors) { + IDataStore dataStore = IDataStore(getDataStore()); + investors = dataStore.getAddressArray(INVESTORSKEY); + } + + /** + * @dev Returns list of investors in a range + */ + function getInvestors(uint256 _fromIndex, uint256 _toIndex) public view returns(address[] memory investors) { + IDataStore dataStore = IDataStore(getDataStore()); + investors = dataStore.getAddressArrayElements(INVESTORSKEY, _fromIndex, _toIndex); + } + + function getAllInvestorFlags() public view returns(address[] memory investors, uint256[] memory flags) { + investors = getAllInvestors(); + flags = new uint256[](investors.length); + for (uint256 i = 0; i < investors.length; i++) { + flags[i] = _getInvestorFlags(investors[i]); + } + } + + function getInvestorFlag(address _investor, uint8 _flag) public view returns(bool value) { + uint256 flag = (_getInvestorFlags(_investor) >> _flag) & ONE; + value = flag > 0 ? true : false; + } + + function getInvestorFlags(address _investor) public view returns(uint256 flags) { + flags = _getInvestorFlags(_investor); + } + + function _getInvestorFlags(address _investor) public view returns(uint256 flags) { + IDataStore dataStore = IDataStore(getDataStore()); + flags = dataStore.getUint256(_getKey(INVESTORFLAGS, _investor)); } /** * @dev Returns list of all investors data */ - function getAllInvestorsData() external view returns( - address[] memory, + function getAllKYCData() external view returns( + address[] memory investors, uint256[] memory fromTimes, uint256[] memory toTimes, - uint256[] memory expiryTimes, - bool[] memory canBuyFromSTOs, - bool[] memory isAccrediteds + uint256[] memory expiryTimes ) { - (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _investorsData(getInvestors()); - return (getInvestors(), fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); - + investors = getAllInvestors(); + (fromTimes, toTimes, expiryTimes) = _kycData(investors); + return (investors, fromTimes, toTimes, expiryTimes); } /** * @dev Returns list of specified investors data */ - function getInvestorsData(address[] calldata _investors) external view returns( - uint256[] memory, + function getKYCData(address[] calldata _investors) external view returns( uint256[] memory, uint256[] memory, - bool[] memory, - bool[] memory + uint256[] memory ) { - return _investorsData(_investors); + return _kycData(_investors); } - function _investorsData(address[] memory _investors) internal view returns( - uint256[] memory, + function _kycData(address[] memory _investors) internal view returns( uint256[] memory, uint256[] memory, - bool[] memory, - bool[] memory + uint256[] memory ) { 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); - bool[] memory isAccrediteds = new bool[](_investors.length); for (uint256 i = 0; i < _investors.length; i++) { - uint8 canBuyFromSTO; - uint8 isAccredited; - (fromTimes[i], toTimes[i], expiryTimes[i], canBuyFromSTO,,isAccredited) = _getValues(_investors[i], IDataStore(getDataStore())); - canBuyFromSTOs[i] = canBuyFromSTO == 0 ? false : true; - isAccrediteds[i] = isAccredited == 0 ? false : true; + (fromTimes[i], toTimes[i], expiryTimes[i], ) = _getKYCValues(_investors[i], IDataStore(getDataStore())); } - return (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); + return (fromTimes, toTimes, expiryTimes); } /** diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index b481e31d5..f246b3675 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -6,28 +6,27 @@ pragma solidity ^0.5.0; contract GeneralTransferManagerStorage { bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) + bytes32 public constant INVESTORFLAGS = "INVESTORFLAGS"; bytes32 public constant FLAGS = "FLAGS"; + uint256 internal constant ONE = uint256(1); //Address from which issuances come - address public issuanceAddress = address(0); + address public issuanceAddress; //Address which can sign whitelist changes - address public signingAddress = address(0); + address public signingAddress; -/* - //from and to timestamps that an investor can send / receive tokens respectively - struct TimeRestriction { - uint64 fromTime; - uint64 toTime; - uint64 expiryTime; - uint8 canBuyFromSTO; - uint8 added; - } - // An address can only send / receive tokens once their corresponding uint256 > block.number - // (unless allowAllTransfers == true or allowAllWhitelistTransfers == true) - mapping (address => TimeRestriction) public whitelist; -*/ + // //from and to timestamps that an investor can send / receive tokens respectively + // // Now Stored in DataStore + // struct TimeRestriction { + // uint64 fromTime; + // uint64 toTime; + // uint64 expiryTime; + // uint8 added; + // } + // Allows all TimeRestrictions to be offset struct Defaults { uint64 fromTime; @@ -37,9 +36,6 @@ contract GeneralTransferManagerStorage { // 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; - // Map of used nonces by customer mapping(address => mapping(uint256 => bool)) public nonceMap; @@ -51,5 +47,5 @@ contract GeneralTransferManagerStorage { bool public allowAllWhitelistIssuances = true; //If true, time lock is ignored for burn transactions bool public allowAllBurnTransfers = false; - + } diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index 267df4f58..4e37c6dd1 100644 --- a/contracts/storage/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -6,6 +6,9 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; * @title Contract used to store layout for the USDTieredSTO storage */ contract USDTieredSTOStorage { + + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) + ///////////// // Storage // ///////////// @@ -27,14 +30,7 @@ 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(address => uint256) public nonAccreditedLimitUSDOverride; mapping(bytes32 => mapping(bytes32 => string)) oracleKeys; @@ -65,16 +61,9 @@ contract USDTieredSTOStorage { // Amount in fund raise type invested by each investor mapping(address => mapping(uint8 => uint256)) public investorInvested; - // Accredited & non-accredited investor data - mapping (address => Investor) public investors; - // List of active stable coin addresses mapping (address => bool) internal 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; diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 4da34cbdb..9f7b7fe59 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -14,6 +14,7 @@ import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; import "../libraries/TokenLib.sol"; +import "../interfaces/IDataStore.sol"; /** * @title Security Token contract @@ -28,7 +29,7 @@ import "../libraries/TokenLib.sol"; contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater { using SafeMath for uint256; - TokenLib.InvestorDataStorage investorData; + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) // Used to hold the semantic version data struct SemanticVersion { @@ -69,6 +70,9 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // Address of the data store used to store shared data address public dataStore; + // Number of investors with non-zero balance + uint256 public holderCount; + // Records added modules - module list should be order agnostic! mapping(uint8 => address[]) modules; @@ -134,8 +138,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater event DisableController(); function _isModule(address _module, uint8 _type) internal view returns(bool) { - require(modulesToData[_module].module == _module, "Wrong address"); - require(!modulesToData[_module].isArchived, "Module archived"); + if (modulesToData[_module].module != _module || modulesToData[_module].isArchived) + return false; for (uint256 i = 0; i < modulesToData[_module].moduleTypes.length; i++) { if (modulesToData[_module].moduleTypes[i] == _type) { return true; @@ -388,7 +392,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @param _value value of transfer */ function _adjustInvestorCount(address _from, address _to, uint256 _value) internal { - TokenLib.adjustInvestorCount(investorData, _from, _to, _value, balanceOf(_to), balanceOf(_from)); + holderCount = TokenLib.adjustInvestorCount(holderCount, _from, _to, _value, balanceOf(_to), balanceOf(_from), dataStore); } /** @@ -396,59 +400,56 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * 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[] memory) { - return investorData.investors; + function getInvestors() public view returns(address[] memory investors) { + IDataStore dataStoreInstance = IDataStore(dataStore); + investors = dataStoreInstance.getAddressArray(INVESTORSKEY); } /** - * @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 + * @notice returns an array of investors with non zero balance at a given checkpoint * @param _checkpointId Checkpoint id at which investor list is to be populated * @return list of investors */ function getInvestorsAt(uint256 _checkpointId) external view returns(address[] memory) { - uint256 count = 0; + uint256 count; uint256 i; - for (i = 0; i < investorData.investors.length; i++) { - if (balanceOfAt(investorData.investors[i], _checkpointId) > 0) { + IDataStore dataStoreInstance = IDataStore(dataStore); + address[] memory investors = dataStoreInstance.getAddressArray(INVESTORSKEY); + for (i = 0; i < investors.length; i++) { + if (balanceOfAt(investors[i], _checkpointId) > 0) { count++; } } - address[] memory investors = new address[](count); + address[] memory holders = 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]; + for (i = 0; i < investors.length; i++) { + if (balanceOfAt(investors[i], _checkpointId) > 0) { + holders[count] = investors[i]; count++; } } - return investors; + return holders; } /** * @notice generates subset of investors - * NB - can be used in batches if investor list is large + * NB - can be used in batches if investor list is large. start and end both are included in array. * @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[] memory) { - 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; + IDataStore dataStoreInstance = IDataStore(dataStore); + return dataStoreInstance.getAddressArrayElements(INVESTORSKEY, _start, _end); } /** - * @notice Returns the investor count + * @notice Returns the count of address that were added as (potential) investors * @return Investor count */ function getInvestorCount() external view returns(uint256) { - return investorData.investorCount; + IDataStore dataStoreInstance = IDataStore(dataStore); + return dataStoreInstance.getAddressArrayLength(INVESTORSKEY); } /** @@ -838,5 +839,4 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater _version[2] = securityTokenVersion.patch; return _version; } - } diff --git a/docs/investor_flags.md b/docs/investor_flags.md new file mode 100644 index 000000000..9ccf74473 --- /dev/null +++ b/docs/investor_flags.md @@ -0,0 +1,23 @@ +# Flags List + + + + + + + + + + + + + + + + + + + + + +
Flag Name Description
0 isAccredited Defines if an Investor is Accredited or not. True for Accredited, false for not Accredited.
1 canNotBuyFromSto Defines if an Investor is restricted from participating in STOs
diff --git a/package.json b/package.json index e8a7e72ef..4c45a49ab 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "scripts": { "test": "scripts/test.sh 2> /dev/null", + "gas": "scripts/gasUsage.sh", "wintest": "scripts\\wintest.cmd", "wincov": "scripts\\wincov.cmd", "docs": "scripts/docs.sh", @@ -85,6 +86,7 @@ "eslint-plugin-node": "^8.0.0", "eslint-plugin-promise": "^4.0.1", "eslint-plugin-standard": "^4.0.0", + "eth-gas-reporter": "^0.1.12", "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", "ganache-cli": "^6.2.4", @@ -95,7 +97,7 @@ "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", "solium": "^1.1.6", - "truffle": "^5.0.0", + "truffle": "^5.0.4", "truffle-wallet-provider": "0.0.5" }, "greenkeeper": { diff --git a/scripts/gasUsage.sh b/scripts/gasUsage.sh new file mode 100755 index 000000000..a7794d371 --- /dev/null +++ b/scripts/gasUsage.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +mv truffle-config.js truffle-config-bk.js +cp truffle-config-gas.js truffle-config.js + +scripts/test.sh + +mv truffle-config-bk.js truffle-config.js \ No newline at end of file diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 8e637736e..8392f189a 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -316,7 +316,7 @@ contract("CappedSTO", async (accounts) => { P_expiryTime = toTime + duration.days(100); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor1, fromTime, toTime, expiryTime, { from: account_issuer }); @@ -386,13 +386,11 @@ contract("CappedSTO", async (accounts) => { it("Should buy the granular unit tokens and refund pending amount", async () => { await I_SecurityToken_ETH.changeGranularity(new BN(10).pow(new BN(21)), { from: token_owner }); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, fromTime, toTime + duration.days(20), expiryTime, - true, - false, { from: account_issuer } @@ -531,7 +529,7 @@ contract("CappedSTO", async (accounts) => { it("Should successfully whitelist investor 3", async () => { balanceOfReceiver = new BN(await web3.eth.getBalance(account_fundsReceiver)); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor3, fromTime, toTime, expiryTime, { from: account_issuer, gas: 500000 }); @@ -697,7 +695,7 @@ contract("CappedSTO", async (accounts) => { 10500, "Tokens are not transfered properly" ); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, P_fromTime, P_toTime, P_expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor1, P_fromTime, P_toTime, P_expiryTime, { from: account_issuer, gas: 500000 }); @@ -756,13 +754,11 @@ contract("CappedSTO", async (accounts) => { it("Should buy the granular unit tokens and charge only required POLY", async () => { await I_SecurityToken_POLY.changeGranularity(new BN(10).pow(new BN(22)), { from: token_owner }); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, P_fromTime, P_toTime + duration.days(20), P_expiryTime, - true, - false, { from: account_issuer, gas: 500000 @@ -973,7 +969,7 @@ contract("CappedSTO", async (accounts) => { await I_PolyToken.getTokens(polyToInvest.mul(new BN(10).pow(new BN(18))), account_investor3); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, P_fromTime, P_toTime, P_expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor3, P_fromTime, P_toTime, P_expiryTime, { from: account_issuer, gas: 500000 }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 707310678..20a1488ce 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -148,13 +148,11 @@ contract("Checkpoints", async function(accounts) { it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist let ltime = new BN(await latestTime()); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, ltime, ltime, ltime.add(new BN(duration.days(10))), - false, - false, { from: account_issuer, gas: 6000000 @@ -175,13 +173,11 @@ contract("Checkpoints", async function(accounts) { it("Should Buy some more tokens", async () => { // Add the Investor in to the whitelist let ltime = new BN(await latestTime()); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, ltime, ltime, ltime.add(new BN(duration.days(10))), - false, - false, { from: account_issuer, gas: 6000000 @@ -202,13 +198,11 @@ contract("Checkpoints", async function(accounts) { it("Add a new token holder", async () => { let ltime = new BN(await latestTime()); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, ltime, ltime, ltime.add(new BN(duration.days(10))), - false, - false, { from: account_issuer, gas: 6000000 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1dd9a544e..64ac16798 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -200,13 +200,11 @@ contract("CountTransferManager", async (accounts) => { it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -231,13 +229,11 @@ contract("CountTransferManager", async (accounts) => { it("Should Buy some more tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -259,13 +255,11 @@ contract("CountTransferManager", async (accounts) => { it("Should able to buy some more tokens (more than 2 hoders) -- because CountTransferManager is paused", async () => { await I_CountTransferManager.pause({ from: account_issuer }); let snapId = await takeSnapshot(); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -285,13 +279,11 @@ contract("CountTransferManager", async (accounts) => { it("Should fail to buy some more tokens (more than 2 holders)", async () => { await I_CountTransferManager.unpause({ from: account_issuer }); // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -374,52 +366,44 @@ contract("CountTransferManager", async (accounts) => { }); it("add 3 holders to the token", async () => { - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 } ); - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 } ); - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 } ); - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor4, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -465,11 +449,11 @@ contract("CountTransferManager", async (accounts) => { 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); - let investorCount = await I_SecurityToken2.getInvestorCount({ from: account_investor2 }); + let investorCount = await I_SecurityToken2.holderCount({ 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)).toString(), amount.toString(), { from: account_investor2 }); - assert(await I_SecurityToken2.getInvestorCount({ from: account_investor2 }), investorCount); + assert(await I_SecurityToken2.holderCount({ from: account_investor2 }), investorCount); }); }); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 577c8dfc0..9a78e96e1 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -209,13 +209,11 @@ contract("ERC20DividendCheckpoint", async (accounts) => { it("Buy some tokens for account_investor1 (1 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(30))), - true, - false, { from: account_issuer, gas: 500000 @@ -240,13 +238,11 @@ contract("ERC20DividendCheckpoint", async (accounts) => { it("Buy some tokens for account_investor2 (2 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(30))), - true, - false, { from: account_issuer, gas: 500000 @@ -387,13 +383,11 @@ contract("ERC20DividendCheckpoint", async (accounts) => { it("Buy some tokens for account_temp (1 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_temp, currentTime, currentTime, currentTime.add(new BN(duration.days(20))), - true, - false, { from: account_issuer, gas: 500000 @@ -451,13 +445,11 @@ contract("ERC20DividendCheckpoint", async (accounts) => { it("Buy some tokens for account_investor3 (7 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(100000))), - true, - false, { from: account_issuer, gas: 500000 diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index ca539b6eb..d59e16ce1 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -203,13 +203,11 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Buy some tokens for account_investor1 (1 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(300000))), - true, - false, { from: account_issuer, gas: 500000 @@ -234,13 +232,11 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Buy some tokens for account_investor2 (2 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(3000000))), - true, - false, { from: account_issuer, gas: 500000 @@ -369,13 +365,11 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Buy some tokens for account_temp (1 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_temp, currentTime, currentTime, currentTime.add(new BN(duration.days(200000))), - true, - false, { from: account_issuer, gas: 500000 @@ -421,13 +415,11 @@ contract("EtherDividendCheckpoint", async (accounts) => { it("Buy some tokens for account_investor3 (7 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10000))), - true, - false, { from: account_issuer, gas: 500000 @@ -728,13 +720,11 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Assign token balance to an address that can't receive funds", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( I_PolyToken.address, currentTime, currentTime, currentTime.add(new BN(duration.days(1000000))), - true, - false, { from: account_issuer, gas: 500000 diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 33fb1edca..b9462c906 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -201,15 +201,30 @@ contract("GeneralTransferManager", async (accounts) => { await revertToSnapshot(snap_id); }); + it("Should add investor flags", async () => { + let snap_id = await takeSnapshot(); + await I_GeneralTransferManager.modifyInvestorFlagMulti([account_investor1, account_investor1, account_investor2], [0, 1, 1], [true, true, true], { from: account_issuer }); + let investors = await I_GeneralTransferManager.getInvestors(0, 1); + assert.equal(investors[0], account_investor1); + assert.equal(investors[1], account_investor2); + let investorCount = await I_SecurityToken.getInvestorCount(); + assert.equal(investorCount.toNumber(), 2); + let allInvestorFlags = await I_GeneralTransferManager.getAllInvestorFlags(); + assert.deepEqual(investors, allInvestorFlags[0]); + assert.equal(allInvestorFlags[1][0].toNumber(), 3)//0x000....00011 + assert.equal(allInvestorFlags[1][1].toNumber(), 2)//0x000....00010 + let investorFlags = await I_GeneralTransferManager.getInvestorFlags(allInvestorFlags[0][0]); + assert.equal(investorFlags, 3)//0x000....00011 + await revertToSnapshot(snap_id); + }); + it("Should whitelist the affiliates before the STO attached", async () => { console.log(`Estimate gas of one Whitelist: - ${await I_GeneralTransferManager.modifyWhitelist.estimateGas( + ${await I_GeneralTransferManager.modifyKYCData.estimateGas( account_affiliates1, currentTime + currentTime.add(new BN(duration.days(30))), currentTime + currentTime.add(new BN(duration.days(90))), currentTime + currentTime.add(new BN(duration.days(965))), - false, - false, { from: account_issuer } @@ -222,31 +237,30 @@ contract("GeneralTransferManager", async (accounts) => { let expiryTime1 = currentTime + currentTime.add(new BN(duration.days(965))); let expiryTime2 = currentTime.add(new BN(duration.days(365))); - let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + let tx = await I_GeneralTransferManager.modifyKYCDataMulti( [account_affiliates1, account_affiliates2], [fromTime1, fromTime2], [toTime1, toTime2], [expiryTime1, expiryTime2], - [false, false], - [false, false], { from: account_issuer, gas: 6000000 } ); + await I_GeneralTransferManager.modifyInvestorFlagMulti([account_affiliates1, account_affiliates2], [1, 1], [true, true], { from: account_issuer }); 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()); - let data = await I_GeneralTransferManager.getInvestorsData.call([account_affiliates1, account_affiliates2]); + assert.deepEqual(await I_GeneralTransferManager.getAllInvestors.call(), [account_affiliates1, account_affiliates2]); + console.log(await I_GeneralTransferManager.getAllKYCData.call()); + let data = await I_GeneralTransferManager.getKYCData.call([account_affiliates1, account_affiliates2]); assert.equal(data[0][0].toString(), fromTime1); assert.equal(data[0][1].toString(), fromTime2); assert.equal(data[1][0].toString(), toTime1); assert.equal(data[1][1].toString(), toTime2); assert.equal(data[2][0].toString(), expiryTime1); assert.equal(data[2][1].toString(), expiryTime2); - assert.isFalse(data[3][0]); - assert.isFalse(data[3][1]); + assert.equal(await I_GeneralTransferManager.getInvestorFlag(account_affiliates1, 1), true); + assert.equal(await I_GeneralTransferManager.getInvestorFlag(account_affiliates2, 1), true); }); it("Should whitelist lots of addresses and check gas", async () => { @@ -257,13 +271,12 @@ contract("GeneralTransferManager", async (accounts) => { let times = range1(50); let bools = rangeB(50); - let tx = await I_GeneralTransferManager.modifyWhitelistMulti(mockInvestors, times, times, times, bools, bools, { - from: account_issuer, - gas: 7900000 + let tx = await I_GeneralTransferManager.modifyKYCDataMulti(mockInvestors, times, times, times, { + from: account_issuer }); console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); assert.deepEqual( - await I_GeneralTransferManager.getInvestors.call(), + await I_GeneralTransferManager.getAllInvestors.call(), [account_affiliates1, account_affiliates2].concat(mockInvestors) ); }); @@ -358,13 +371,11 @@ contract("GeneralTransferManager", async (accounts) => { it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 @@ -422,7 +433,7 @@ contract("GeneralTransferManager", async (accounts) => { 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, new BN(0), new BN(0), currentTime.add(new BN(duration.days(20))), true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor1, new BN(0), new BN(0), currentTime.add(new BN(duration.days(20))), { from: account_issuer, gas: 6000000 }); @@ -433,13 +444,11 @@ contract("GeneralTransferManager", async (accounts) => { "Failed in adding the investor in whitelist" ); - tx = await I_GeneralTransferManager.modifyWhitelist( + tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(20))), - true, - true, { from: account_issuer, gas: 6000000 @@ -476,7 +485,7 @@ contract("GeneralTransferManager", async (accounts) => { await increaseTime(duration.days(2)); await I_SecurityToken.transfer(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: account_investor2 }); // revert changes - await I_GeneralTransferManager.modifyWhitelist(account_investor2, new BN(0), new BN(0), new BN(0), false, false, { + await I_GeneralTransferManager.modifyKYCData(account_investor2, new BN(0), new BN(0), new BN(0), { from: account_issuer, gas: 6000000 }); @@ -517,8 +526,6 @@ contract("GeneralTransferManager", async (accounts) => { fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -526,13 +533,11 @@ contract("GeneralTransferManager", async (accounts) => { ); await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( + I_GeneralTransferManager.modifyKYCDataSigned( account_investor2, fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -557,8 +562,6 @@ contract("GeneralTransferManager", async (accounts) => { fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -566,13 +569,11 @@ contract("GeneralTransferManager", async (accounts) => { ); await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( + I_GeneralTransferManager.modifyKYCDataSigned( account_investor2, fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -597,8 +598,6 @@ contract("GeneralTransferManager", async (accounts) => { fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -606,13 +605,11 @@ contract("GeneralTransferManager", async (accounts) => { ); await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( + I_GeneralTransferManager.modifyKYCDataSigned( account_investor2, fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -637,21 +634,17 @@ contract("GeneralTransferManager", async (accounts) => { currentTime.toNumber(), currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), - true, - false, validFrom, validTo, nonce, signer.privateKey ); - let tx = await I_GeneralTransferManager.modifyWhitelistSigned( + let tx = await I_GeneralTransferManager.modifyKYCDataSigned( account_investor2, currentTime.toNumber(), currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), - true, - false, validFrom, validTo, nonce, @@ -689,8 +682,6 @@ contract("GeneralTransferManager", async (accounts) => { currentTime.toNumber(), currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), - true, - false, validFrom, validTo, nonce, @@ -698,13 +689,11 @@ contract("GeneralTransferManager", async (accounts) => { ); await catchRevert( - I_GeneralTransferManager.modifyWhitelistSigned( + I_GeneralTransferManager.modifyKYCDataSigned( account_investor2, currentTime.toNumber(), currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), - true, - false, validFrom, validTo, nonce, @@ -729,21 +718,17 @@ contract("GeneralTransferManager", async (accounts) => { currentTime.toNumber(), currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), - true, - false, validFrom, validTo, nonce, "0x" + token_owner_pk ); - await I_GeneralTransferManager.modifyWhitelistSigned( + await I_GeneralTransferManager.modifyKYCDataSigned( account_investor2, currentTime.toNumber(), currentTime.add(new BN(duration.days(100))).toNumber(), expiryTime + duration.days(200), - true, - false, validFrom, validTo, nonce, @@ -827,13 +812,11 @@ contract("GeneralTransferManager", async (accounts) => { let expiryTime = toTime + duration.days(10); await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( + I_GeneralTransferManager.modifyKYCDataMulti( [account_investor3, account_investor4], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], - [true, true], { from: account_delegate, gas: 6000000 @@ -848,13 +831,11 @@ contract("GeneralTransferManager", async (accounts) => { let expiryTime = toTime + duration.days(10); await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( + I_GeneralTransferManager.modifyKYCDataMulti( [account_investor3, account_investor4], [fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], - [true, true], { from: account_delegate, gas: 6000000 @@ -869,13 +850,11 @@ contract("GeneralTransferManager", async (accounts) => { let expiryTime = toTime + duration.days(10); await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( + I_GeneralTransferManager.modifyKYCDataMulti( [account_investor3, account_investor4], [fromTime, fromTime], [toTime], [expiryTime, expiryTime], - [true, true], - [true, true], { from: account_delegate, gas: 6000000 @@ -890,13 +869,11 @@ contract("GeneralTransferManager", async (accounts) => { let expiryTime = toTime + duration.days(10); await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( + I_GeneralTransferManager.modifyKYCDataMulti( [account_investor3, account_investor4], [fromTime, fromTime], [toTime, toTime], [expiryTime], - [true, true], - [true, true], { from: account_delegate, gas: 6000000 @@ -910,13 +887,11 @@ contract("GeneralTransferManager", async (accounts) => { let toTime = await latestTime() + duration.days(20); let expiryTime = toTime + duration.days(10); - let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + let tx = await I_GeneralTransferManager.modifyKYCDataMulti( [account_investor3, account_investor4], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [true, true], - [true, true], { from: token_owner, gas: 6000000 diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 73a2ff761..0d675d7a7 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -5,11 +5,11 @@ const Web3 = require("web3"); let BN = Web3.utils.BN; //this, _investor, _fromTime, _toTime, _validTo -function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce, pk) { +function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, validFrom, validTo, nonce, pk) { let packedData = utils .solidityKeccak256( - ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256", "uint256"], - [tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, nonce] + ["address", "address", "uint256", "uint256", "uint256", "uint256", "uint256", "uint256"], + [tmAddress, investorAddress, fromTime, toTime, expiryTime, validFrom, validTo, nonce] ) .slice(2); packedData = new Buffer(packedData, "hex"); @@ -27,8 +27,8 @@ function getSignSTMData(tmAddress, nonce, expiry, fromAddress, toAddress, amount return data; } -function getSignGTMData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, accredited, validFrom, validTo, nonce, pk) { - let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: investorAddress}, {t: 'uint256', v: new BN(fromTime)}, {t: 'uint256', v: new BN(toTime)}, {t: 'uint256', v: new BN(expiryTime)}, {t: 'bool', v: restricted}, {t: 'bool', v: accredited}, {t: 'uint256', v: new BN(validFrom)}, {t: 'uint256', v: new BN(validTo)}, {t: 'uint256', v: new BN(nonce)}); +function getSignGTMData(tmAddress, investorAddress, fromTime, toTime, expiryTime, validFrom, validTo, nonce, pk) { + let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'address', v: investorAddress}, {t: 'uint256', v: new BN(fromTime)}, {t: 'uint256', v: new BN(toTime)}, {t: 'uint256', v: new BN(expiryTime)}, {t: 'uint256', v: new BN(validFrom)}, {t: 'uint256', v: new BN(validTo)}, {t: 'uint256', v: new BN(nonce)}); let signature = (web3.eth.accounts.sign(hash, pk)); return signature.signature; } diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 321f6c8d5..78291f7dd 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -205,13 +205,11 @@ contract("Issuance", async (accounts) => { toTime = await latestTime() + duration.days(15); expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, fromTime + duration.days(70), toTime + duration.days(90), expiryTime + duration.days(50), - true, - false, { from: account_polymath } @@ -271,7 +269,7 @@ contract("Issuance", async (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, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor2, fromTime, toTime, expiryTime, { from: account_delegate, gas: 7000000 }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index bb4b10403..2d3244e38 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -170,13 +170,11 @@ contract("ManualApprovalTransferManager", accounts => { it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(30))), - true, - false, { from: account_issuer, gas: 6000000 @@ -201,13 +199,11 @@ contract("ManualApprovalTransferManager", accounts => { it("Should Buy some more tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(30))), - true, - false, { from: account_issuer, gas: 6000000 @@ -291,13 +287,11 @@ contract("ManualApprovalTransferManager", accounts => { }); it("Add a new token holder", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 880f87606..eafc4fd42 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -197,13 +197,11 @@ contract("PercentageTransferManager", async (accounts) => { it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 @@ -228,13 +226,11 @@ contract("PercentageTransferManager", async (accounts) => { it("Should Buy some more tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 @@ -294,13 +290,11 @@ contract("PercentageTransferManager", async (accounts) => { }); it("Add a new token holder", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index b5056bf0a..c323fd1b3 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -241,7 +241,7 @@ contract("PreSaleSTO", async (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, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor1, fromTime, toTime, expiryTime, { from: account_issuer, gas: 6000000 }); @@ -282,7 +282,7 @@ contract("PreSaleSTO", async (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, false, { + let tx1 = await I_GeneralTransferManager.modifyKYCData(account_investor2, fromTime, toTime, expiryTime, { from: account_issuer, gas: 6000000 }); @@ -290,7 +290,7 @@ contract("PreSaleSTO", async (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, false, { + let tx2 = await I_GeneralTransferManager.modifyKYCData(account_investor3, fromTime, toTime, expiryTime, { from: account_issuer, gas: 6000000 }); diff --git a/test/o_security_token.js b/test/o_security_token.js index e5a2a1d40..38fb10c81 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -199,7 +199,7 @@ contract("SecurityToken", async (accounts) => { let toTime = new BN(currentTime.add(new BN(duration.days(100)))); let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate1, currentTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_affiliate1, currentTime, toTime, expiryTime, { from: token_owner, gas: 6000000 }); @@ -218,7 +218,7 @@ contract("SecurityToken", async (accounts) => { let toTime = new BN(currentTime.add(new BN(duration.days(100)))); let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_affiliate2, currentTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_affiliate2, currentTime, toTime, expiryTime, { from: token_owner, gas: 6000000 }); @@ -536,7 +536,7 @@ contract("SecurityToken", async (accounts) => { toTime = fromTime + duration.days(100); expiryTime = toTime + duration.days(100); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor1, fromTime, toTime, expiryTime, { from: token_owner, gas: 6000000 }); @@ -648,7 +648,7 @@ contract("SecurityToken", async (accounts) => { }); it("Should transfer from whitelist investor1 to whitelist investor 2", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor2, fromTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor2, fromTime, toTime, expiryTime, { from: token_owner, gas: 500000 }); @@ -670,7 +670,7 @@ contract("SecurityToken", async (accounts) => { it("Should transferFrom from one investor to other", async () => { await I_SecurityToken.approve(account_investor1, new BN(2).mul(new BN(10).pow(new BN(18))), { from: account_investor2 }); - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor3, fromTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor3, fromTime, toTime, expiryTime, { from: token_owner, gas: 500000 }); @@ -715,7 +715,7 @@ contract("SecurityToken", async (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, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_temp, fromTime, toTime, expiryTime, { from: account_delegate, gas: 6000000 }); @@ -755,7 +755,7 @@ contract("SecurityToken", async (accounts) => { }); it("Should remove investor from the whitelist by the delegate", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, new BN(0), new BN(0), new BN(0), true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_temp, new BN(0), new BN(0), new BN(0), { from: account_delegate, gas: 6000000 }); @@ -784,7 +784,7 @@ contract("SecurityToken", async (accounts) => { }); it("Should fail in buying to tokens", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist(account_temp, fromTime, toTime, expiryTime, true, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_temp, fromTime, toTime, expiryTime, { from: account_delegate, gas: 6000000 }); @@ -863,7 +863,6 @@ contract("SecurityToken", async (accounts) => { it("Should force burn the tokens - value too high", async () => { await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, { from: token_owner }); - let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); await catchRevert( I_SecurityToken.forceBurn(account_temp, currentBalance + new BN(web3.utils.toWei("500", "ether")), "0x0", "0x0", { @@ -873,19 +872,18 @@ contract("SecurityToken", async (accounts) => { }); it("Should force burn the tokens - wrong caller", async () => { await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, { from: token_owner }); - let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); await catchRevert(I_SecurityToken.forceBurn(account_temp, currentBalance, "0x0", "0x0", { from: token_owner })); }); it("Should burn the tokens", async () => { - let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); + let currentInvestorCount = await I_SecurityToken.holderCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); // console.log(currentInvestorCount.toString(), currentBalance.toString()); let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "0x0", "0x0", { from: account_controller }); // console.log(tx.logs[1].args._value.toNumber(), currentBalance.toNumber()); assert.equal(tx.logs[1].args._value.toString(), currentBalance.toString()); - let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); + let newInvestorCount = await I_SecurityToken.holderCount.call(); // console.log(newInvestorCount.toString()); assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); }); @@ -928,17 +926,17 @@ contract("SecurityToken", async (accounts) => { 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); + let filteredInvestors = await I_SecurityToken.iterateInvestors.call(0, 0); + console.log("Filtered Investors (0, 0): " + 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); + filteredInvestors = await I_SecurityToken.iterateInvestors.call(2, 3); + console.log("Filtered Investors (2, 3): " + 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); + filteredInvestors = await I_SecurityToken.iterateInvestors.call(0, 3); + console.log("Filtered Investors (0, 3): " + filteredInvestors); assert.equal(filteredInvestors[0], investors[0]); assert.equal(filteredInvestors[1], investors[1]); assert.equal(filteredInvestors[2], investors[2]); @@ -965,13 +963,11 @@ contract("SecurityToken", async (accounts) => { I_MockRedemptionManager = await MockRedemptionManager.at(tx.logs[2].args._module); // adding the burn module into the GTM currentTime = new BN(await latestTime()); - tx = await I_GeneralTransferManager.modifyWhitelist( + tx = await I_GeneralTransferManager.modifyKYCData( I_MockRedemptionManager.address, currentTime, currentTime.add(new BN(duration.seconds(2))), currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_delegate, gas: 6000000 @@ -1008,13 +1004,11 @@ contract("SecurityToken", async (accounts) => { // adding the burn module into the GTM currentTime = new BN(await latestTime()); - tx = await I_GeneralTransferManager.modifyWhitelist( + tx = await I_GeneralTransferManager.modifyKYCData( I_MockRedemptionManager.address, currentTime, currentTime.add(new BN(duration.seconds(2))), currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_delegate, gas: 6000000 @@ -1095,7 +1089,7 @@ contract("SecurityToken", async (accounts) => { let sender = account_investor1; let receiver = account_investor2; - let start_investorCount = await I_SecurityToken.getInvestorCount.call(); + let start_investorCount = await I_SecurityToken.holderCount.call(); let start_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); let start_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); @@ -1108,7 +1102,7 @@ contract("SecurityToken", async (accounts) => { { from: account_controller } ); - let end_investorCount = await I_SecurityToken.getInvestorCount.call(); + let end_investorCount = await I_SecurityToken.holderCount.call(); let end_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); let end_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1da3d9f20..4e3983966 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1010,15 +1010,13 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); //set as Accredited + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { 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 = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH let investment_POLY = new BN(web3.utils.toWei("10000", "ether")); // Invest 10000 POLY @@ -1056,14 +1054,14 @@ contract("USDTieredSTO", async (accounts) => { // 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.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted,{ from: ISSUER }); + // await I_GeneralTransferManager.modifyKYCData(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 }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); // Prep for investments let investment_ETH = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH @@ -1110,15 +1108,13 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { 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 = new BN(2).mul(e18); let investment_ETH = await convert(stoId, tierId, false, "USD", "ETH", investment_USD); let investment_POLY = await convert(stoId, tierId, false, "USD", "POLY", investment_USD); @@ -1165,15 +1161,13 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted,false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { 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"); @@ -1235,15 +1229,13 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime.add(new BN(duration.days(100))); let whitelisted = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { 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); @@ -1282,17 +1274,15 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { 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 = new BN(web3.utils.toWei("1", "ether")); // Invest 1 ETH let investment_POLY = new BN(web3.utils.toWei("10000", "ether")); // Invest 10000 POLY @@ -1337,16 +1327,14 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, whitelisted, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(RESERVEWALLET, fromTime, toTime, expiryTime, whitelisted, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(RESERVEWALLET, fromTime, toTime, expiryTime, { 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"); @@ -1405,35 +1393,19 @@ contract("USDTieredSTO", async (accounts) => { let expiryTime = toTime + duration.days(100); let whitelisted = true; - const tx1 = await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, whitelisted, false, { + const tx1 = await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { 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, true, { + const tx2 = await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { 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 () => { + it("should successfully modify accredited addresses for the STOs", async () => { let stoId = 0; - 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 }); - 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 }); - 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(); console.log(totalStatus); assert.equal(totalStatus[0][0], NONACCREDITED1, "Account match"); @@ -1442,19 +1414,6 @@ contract("USDTieredSTO", async (accounts) => { 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 })); - }); - - 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 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"); }); }); @@ -1862,8 +1821,6 @@ contract("USDTieredSTO", async (accounts) => { let stoId = 0; let tierId = 0; - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - let investment_Token = new BN(50).mul(e18); let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); @@ -2163,8 +2120,8 @@ contract("USDTieredSTO", async (accounts) => { await I_USDTieredSTO_Array[stoId].changeNonAccreditedLimit([NONACCREDITED1], [_nonAccreditedLimitUSD[stoId].div(new BN(2))], { from: ISSUER }); - let investorStatus = await I_USDTieredSTO_Array[stoId].investors.call(NONACCREDITED1); - console.log("Current limit: " + investorStatus[2].toString()); + let investorLimit = await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride.call(NONACCREDITED1); + console.log("Current limit: " + investorLimit.toString()); let totalStatus = await I_USDTieredSTO_Array[stoId].getAccreditedData.call(); assert.equal(totalStatus[0][0], NONACCREDITED1, "Account match"); @@ -2179,8 +2136,7 @@ contract("USDTieredSTO", async (accounts) => { let stoId = 0; let tierId = 0; - 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_USD = await I_USDTieredSTO_Array[stoId].nonAccreditedLimitUSDOverride.call(NONACCREDITED1);//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); @@ -2665,8 +2621,6 @@ contract("USDTieredSTO", async (accounts) => { 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()).toString(), startTier, @@ -3440,8 +3394,6 @@ contract("USDTieredSTO", async (accounts) => { let stoId = 2; let tierId = 0; - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); - let investment_Token = new BN(5).mul(e18); let investment_USD = await convert(stoId, tierId, false, "TOKEN", "USD", investment_Token); let investment_ETH = await convert(stoId, tierId, false, "TOKEN", "ETH", investment_Token); @@ -3846,7 +3798,6 @@ contract("USDTieredSTO", async (accounts) => { await I_SecurityToken.changeGranularity(e18, { from: ISSUER }); let stoId = 4; let tierId = 0; - await I_USDTieredSTO_Array[stoId].changeAccredited([ACCREDITED1], [true], { from: ISSUER }); let investment_Tokens = new BN(1050).mul(e16); let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Tokens); @@ -4062,7 +4013,6 @@ contract("USDTieredSTO", async (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 BN(e18); let investment_POLY = await convert(stoId, tierId, true, "TOKEN", "POLY", investment_Tokens); let investment_ETH = await convert(stoId, tierId, true, "TOKEN", "ETH", investment_Tokens); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 8862bab3d..30e72d055 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -372,17 +372,20 @@ contract("USDTieredSTO Sim", async (accounts) => { let expiryTime = toTime + duration.days(100); let canBuyFromSTO = true; - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(ACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, true, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED1, fromTime, toTime, expiryTime, canBuyFromSTO, false, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NONACCREDITED2, fromTime, toTime, expiryTime, canBuyFromSTO, false, { from: ISSUER }); - await I_GeneralTransferManager.modifyWhitelist(NOTAPPROVED, fromTime, toTime, expiryTime, false, false, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(ACCREDITED2, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED2, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NONACCREDITED2, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyKYCData(NOTAPPROVED, fromTime, toTime, expiryTime, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(NOTAPPROVED, 1, true, { 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 }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { from: ISSUER }); + await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED2, 0, true, { from: ISSUER }); }); }); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index e25647af3..e36207717 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -167,7 +167,7 @@ contract("Concurrent STO", async (accounts) => { let expiryTime = toTime + duration.days(100); let canBuyFromSTO = true; - let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, canBuyFromSTO, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(account_investor1, fromTime, toTime, expiryTime, { from: account_issuer, gas: 500000 }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index ad9f588b1..dd22c1c51 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -187,13 +187,11 @@ contract("TrackedRedemption", async (accounts) => { it("Buy some tokens for account_investor1 (1 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(30))), - true, - false, { from: account_issuer, gas: 500000 @@ -218,13 +216,11 @@ contract("TrackedRedemption", async (accounts) => { it("Buy some tokens for account_investor2 (2 ETH)", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(30))), - true, - false, { from: account_issuer, gas: 500000 diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index ac54788a1..7e0a59ae2 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -197,13 +197,11 @@ contract('LockUpTransferManager', accounts => { it("Should Buy the tokens from non-divisible", async() => { // Add the Investor in to the whitelist console.log(account_investor1); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer }); @@ -225,13 +223,11 @@ contract('LockUpTransferManager', accounts => { it("Should Buy some more tokens from non-divisible tokens", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer }); @@ -296,13 +292,11 @@ contract('LockUpTransferManager', accounts => { it("Add a new token holder", async() => { - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer }); diff --git a/test/x_scheduled_checkpoints.js b/test/x_scheduled_checkpoints.js index 745aa0ab0..536ace060 100644 --- a/test/x_scheduled_checkpoints.js +++ b/test/x_scheduled_checkpoints.js @@ -177,13 +177,11 @@ contract("ScheduledCheckpoint", async (accounts) => { // Add the Investor in to the whitelist console.log("3: " + await latestTime()); - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 @@ -223,13 +221,11 @@ contract("ScheduledCheckpoint", async (accounts) => { it("Should Buy some more tokens for account_investor2", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 @@ -260,13 +256,11 @@ contract("ScheduledCheckpoint", async (accounts) => { }); it("Add a new token holder - account_investor3", async () => { - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 6000000 diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index c46fe3a9c..5fac4428a 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -224,13 +224,11 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Transfer some tokens to different account", async() => { // Add tokens in to the whitelist let newLatestTime = await getLatestTime(); - await I_GeneralTransferManager.modifyWhitelistMulti( + await I_GeneralTransferManager.modifyKYCDataMulti( [account_investor1, account_investor2, account_investor3], [newLatestTime, newLatestTime, newLatestTime], [newLatestTime, newLatestTime, newLatestTime], [newLatestTime.add(new BN(duration.days(60))), newLatestTime.add(new BN(duration.days(60))), newLatestTime.add(new BN(duration.days(60)))], - [true, true, true], - [false,false,false], { from: token_owner } @@ -1299,13 +1297,11 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Should add the investor 4 in the whitelist", async() => { let newLatestTime = await getLatestTime(); - await I_GeneralTransferManager.modifyWhitelist( + await I_GeneralTransferManager.modifyKYCData( account_investor4, newLatestTime, newLatestTime, newLatestTime.add(new BN(duration.days(30))), - true, - false, { from: token_owner } diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index 0038052b6..f34c3e9e9 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -214,13 +214,11 @@ contract('BlacklistTransferManager', accounts => { it("Should Buy the tokens", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_issuer }); @@ -242,13 +240,11 @@ contract('BlacklistTransferManager', accounts => { it("Should Buy some more tokens", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor2, currentTime, currentTime, currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_issuer }); @@ -267,13 +263,11 @@ contract('BlacklistTransferManager', accounts => { it("Should Buy some more tokens", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor3, currentTime, currentTime, currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_issuer }); @@ -292,13 +286,11 @@ contract('BlacklistTransferManager', accounts => { it("Should Buy some more tokens", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor4, currentTime, currentTime, currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_issuer }); @@ -317,13 +309,11 @@ contract('BlacklistTransferManager', accounts => { it("Should Buy some more tokens", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor5, currentTime, currentTime, currentTime.add(new BN(duration.days(50))), - true, - false, { from: account_issuer }); diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index c9e5f56d8..2f0a80195 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -212,13 +212,11 @@ contract('VolumeRestrictionTransferManager', accounts => { it("Transfer some tokens to different account", async() => { // Add tokens in to the whitelist currentTime = new BN(await latestTime()); - await I_GeneralTransferManager.modifyWhitelistMulti( + await I_GeneralTransferManager.modifyKYCDataMulti( [account_investor1, account_investor2, account_investor3], [currentTime, currentTime, currentTime], [currentTime, currentTime, currentTime], [currentTime.add(new BN(duration.days(60))), currentTime.add(new BN(duration.days(60))), currentTime.add(new BN(duration.days(60)))], - [true, true, true], - [false, false, false], { from: token_owner } diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index b78b07b43..86d723299 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -353,18 +353,16 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { console.log("3"); if (randomPerms === "WHITELIST") { - let tx = await I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, false, { + let tx = await I_GeneralTransferManager.modifyKYCData(accounts[j], fromTime, toTime, expiryTime, { from: accounts[j] }); assert.equal(tx.logs[0].args._investor, accounts[j]); console.log("3.1"); - let tx2 = await I_GeneralTransferManager.modifyWhitelistMulti( + let tx2 = await I_GeneralTransferManager.modifyKYCDataMulti( [accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], - [false, false], { from: accounts[j] } ); console.log(tx2.logs[1].args); @@ -373,17 +371,15 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { } else { console.log("3.3"); await catchRevert( - I_GeneralTransferManager.modifyWhitelist(accounts[j], fromTime, toTime, expiryTime, 1, false, { from: accounts[j] }) + I_GeneralTransferManager.modifyKYCData(accounts[j], fromTime, toTime, expiryTime, { from: accounts[j] }) ); console.log("3.4"); await catchRevert( - I_GeneralTransferManager.modifyWhitelistMulti( + I_GeneralTransferManager.modifyKYCDataMulti( [accounts[3], accounts[4]], [fromTime, fromTime], [toTime, toTime], [expiryTime, expiryTime], - [1, 1], - [false, false], { from: accounts[j] } ) ); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index 57f102052..c80744dc5 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -193,13 +193,11 @@ contract('VestingEscrowWallet', accounts => { it("Should Buy the tokens for token_owner", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( token_owner, currentTime, currentTime, currentTime.add(new BN(durationUtil.days(10))), - true, - false, { from: token_owner, gas: 6000000 @@ -220,13 +218,11 @@ contract('VestingEscrowWallet', accounts => { it("Should whitelist investors", async() => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelistMulti( + let tx = await I_GeneralTransferManager.modifyKYCDataMulti( [I_VestingEscrowWallet.address, account_beneficiary1, account_beneficiary2, account_beneficiary3], [currentTime, currentTime, currentTime, currentTime], [currentTime, currentTime, currentTime, currentTime], [currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10))), currentTime.add(new BN(durationUtil.days(10)))], - [true, true, true, true], - [false, false, false, false], { from: token_owner, gas: 6000000 diff --git a/test/za_datastore.js b/test/za_datastore.js index aa3860151..526583c21 100644 --- a/test/za_datastore.js +++ b/test/za_datastore.js @@ -218,6 +218,8 @@ contract("Data store", async (accounts) => { let arrLen = await I_DataStore.getUint256ArrayLength(key); await I_DataStore.insertUint256(key, new BN(10), { from: token_owner }); let arrElement = await I_DataStore.getUint256ArrayElement(key, arrLen.toNumber()); + let arrElements = await I_DataStore.getUint256ArrayElements(key, 0, arrLen.toNumber()); + assert.equal(arrElement.toNumber(), arrElements[arrLen.toNumber()].toNumber()); assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getUint256ArrayLength(key)).toNumber(), "Incorrect Array Length"); assert.equal(arrElement.toNumber(), 10, "Incorrect array element"); }); @@ -226,6 +228,8 @@ contract("Data store", async (accounts) => { let arrLen = await I_DataStore.getBytes32ArrayLength(key); await I_DataStore.insertBytes32(key, bytes32data, { from: token_owner }); let arrElement = await I_DataStore.getBytes32ArrayElement(key, arrLen.toNumber()); + let arrElements = await I_DataStore.getBytes32ArrayElements(key, 0, arrLen.toNumber()); + assert.equal(arrElement, arrElements[arrLen.toNumber()]); assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBytes32ArrayLength(key)).toNumber(), "Incorrect Array Length"); assert.equal(arrElement, bytes32data, "Incorrect array element"); }); @@ -234,6 +238,8 @@ contract("Data store", async (accounts) => { let arrLen = await I_DataStore.getAddressArrayLength(key); await I_DataStore.insertAddress(key, address_one, { from: token_owner }); let arrElement = await I_DataStore.getAddressArrayElement(key, arrLen.toNumber()); + let arrElements = await I_DataStore.getAddressArrayElements(key, 0, arrLen.toNumber()); + assert.equal(arrElement, arrElements[arrLen.toNumber()]); assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getAddressArrayLength(key)).toNumber(), "Incorrect Array Length"); assert.equal(arrElement, address_one, "Incorrect array element"); }); @@ -242,6 +248,8 @@ contract("Data store", async (accounts) => { let arrLen = await I_DataStore.getBoolArrayLength(key); await I_DataStore.insertBool(key, true, { from: token_owner }); let arrElement = await I_DataStore.getBoolArrayElement(key, arrLen.toNumber()); + let arrElements = await I_DataStore.getBoolArrayElements(key, 0, arrLen.toNumber()); + assert.equal(arrElement, arrElements[arrLen.toNumber()]); assert.equal(arrLen.toNumber() + 1, (await I_DataStore.getBoolArrayLength(key)).toNumber(), "Incorrect Array Length"); assert.equal(arrElement, true, "Incorrect array element"); }); diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index 105729b14..98a81ca35 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -160,13 +160,11 @@ contract("SignedTransferManager", accounts => { it("Should Buy the tokens", async () => { // Add the Investor in to the whitelist - let tx = await I_GeneralTransferManager.modifyWhitelist( + let tx = await I_GeneralTransferManager.modifyKYCData( account_investor1, currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer } diff --git a/truffle-config-gas.js b/truffle-config-gas.js new file mode 100644 index 000000000..8f690985f --- /dev/null +++ b/truffle-config-gas.js @@ -0,0 +1,81 @@ +require('babel-register'); +require('babel-polyfill'); +const fs = require('fs'); +const NonceTrackerSubprovider = require("web3-provider-engine/subproviders/nonce-tracker") + +const HDWalletProvider = require("truffle-hdwallet-provider-privkey"); + +module.exports = { + networks: { + development: { + host: 'localhost', + port: 8545, + network_id: '*', // Match any network id + gas: 7900000, + }, + mainnet: { + host: 'localhost', + port: 8545, + network_id: '1', // Match any network id + gas: 7900000, + gasPrice: 10000000000 + }, + ropsten: { + // provider: new HDWalletProvider(privKey, "http://localhost:8545"), + host: 'localhost', + port: 8545, + network_id: '3', // Match any network id + gas: 4500000, + gasPrice: 150000000000 + }, + rinkeby: { + // provider: new HDWalletProvider(privKey, "http://localhost:8545"), + host: 'localhost', + port: 8545, + network_id: '4', // Match any network id + gas: 7500000, + gasPrice: 10000000000 + }, + kovan: { + provider: () => { + const key = fs.readFileSync('./privKey').toString(); + let wallet = new HDWalletProvider(key, "https://kovan.infura.io/") + var nonceTracker = new NonceTrackerSubprovider() + wallet.engine._providers.unshift(nonceTracker) + nonceTracker.setEngine(wallet.engine) + return wallet + }, + network_id: '42', // Match any network id + gas: 7900000, + gasPrice: 5000000000 + }, + coverage: { + host: "localhost", + network_id: "*", + port: 8545, // <-- If you change this, also set the port option in .solcover.js. + gas: 0xfffffffff , // <-- Use this high gas value + gasPrice: 0x01 // <-- Use this low gas price + } + }, + compilers: { + solc: { + version: "native", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + } + }, + mocha: { + enableTimeouts: false, + reporter: 'eth-gas-reporter', + reporterOptions : { + currency: 'USD', + gasPrice: 5, + onlyCalledMethods: true, + showTimeSpent: true + } + } +}; diff --git a/yarn.lock b/yarn.lock index acb5a45dc..04adc5fef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33,10 +33,44 @@ valid-url "^1.0.9" yargs "^11.0.0" +"@types/concat-stream@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.0.tgz#394dbe0bb5fee46b38d896735e8b68ef2390d00d" + integrity sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0= + dependencies: + "@types/node" "*" + +"@types/form-data@0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + integrity sha1-yayFsqX9GENbjIXZ7LUObWyJP/g= + dependencies: + "@types/node" "*" + +"@types/node@*": + version "11.9.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.3.tgz#14adbb5ab8cd563f549fbae8dbe92e0b7d6e76cc" + integrity sha512-DMiqG51GwES/c4ScBY0u5bDlH44+oY8AeYHjY1SGCWidD7h08o1dfHue/TGK7REmif2KiJzaUskO+Q0eaeZ2fQ== + "@types/node@^10.3.2": version "10.12.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.2.tgz#d77f9faa027cadad9c912cd47f4f8b07b0fb0864" +"@types/node@^8.0.0": + version "8.10.40" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.40.tgz#4314888d5cd537945d73e9ce165c04cc550144a4" + integrity sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ== + +"@types/node@^9.3.0", "@types/node@^9.4.1": + version "9.6.42" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.42.tgz#96fd9c8cf15fbf2c16fe525fc2be97c49cdd0c2f" + integrity sha512-SpeVQJFekfnEaZZO1yl4je/36upII36L7gOT4DBx51B1GeAB45mmDb3a5OBQB+ZeFxVVOP37r8Owsl940G/fBg== + +"@types/qs@^6.2.31": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.1.tgz#a38f69c62528d56ba7bd1f91335a8004988d72f7" + integrity sha512-mNhVdZHdtKHMMxbqzNK3RzkBcN1cux3AvuCYGTvjEIQT2uheH3eCAyYsbMbh2Bq8nXkeOWs1kyDiF7geWRFQ4Q== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -45,6 +79,13 @@ abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" +abi-decoder@^1.0.8: + version "1.2.0" + resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.2.0.tgz#c42882dbb91b444805f0cd203a87a5cc3c22f4a8" + integrity sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg== + dependencies: + web3 "^0.18.4" + abstract-leveldown@~2.6.0: version "2.6.3" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" @@ -257,6 +298,11 @@ array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1387,7 +1433,7 @@ chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" -charenc@~0.0.1: +"charenc@>= 0.0.1", charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -1472,6 +1518,16 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1584,6 +1640,16 @@ 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.4.6, 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" + 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" @@ -1711,7 +1777,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -crypt@~0.0.1: +"crypt@>= 0.0.1", crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" @@ -2402,6 +2468,24 @@ eth-block-tracker@^2.2.2: pify "^2.3.0" tape "^4.6.3" +eth-gas-reporter@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.1.12.tgz#6b761e05c33ae85be47840dd07468ab51d473dd8" + integrity sha512-Ao5uiXSA5Ep5fi/YvGCsFJMelMKj0fMJkAvWYzPVe1h3Mg9Z7X3Rs51ovG9izFZH7wSqnqydiC6SKDhZWpxK2g== + dependencies: + abi-decoder "^1.0.8" + cli-table3 "^0.5.0" + colors "^1.1.2" + lodash "^4.17.4" + mocha "^4.1.0" + req-cwd "^2.0.0" + request "^2.83.0" + request-promise-native "^1.0.5" + sha1 "^1.1.1" + shelljs "^0.7.8" + solidity-parser-antlr "^0.2.10" + sync-request "^6.0.0" + 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" @@ -2956,7 +3040,7 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" -form-data@~2.3.2: +form-data@^2.2.0, form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" dependencies: @@ -3087,6 +3171,11 @@ 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" +get-port@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= + get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" @@ -3362,6 +3451,18 @@ 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" +http-basic@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-7.0.0.tgz#82f0a506be942732ec8deebee80e746ef5736dba" + integrity sha1-gvClBr6UJzLsje6+6A50bvVzbbo= + dependencies: + "@types/concat-stream" "^1.6.0" + "@types/node" "^9.4.1" + caseless "~0.12.0" + concat-stream "^1.4.6" + http-response-object "^3.0.1" + parse-cache-control "^1.0.1" + 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" @@ -3375,6 +3476,13 @@ http-https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" +http-response-object@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.1.tgz#90174d44c27b5e797cf6efe51a043bc889ae64bf" + integrity sha512-6L0Fkd6TozA8kFSfh9Widst0wfza3U1Ex2RjJ6zNDK0vR1U1auUR6jY4Nn2Xl7CCy0ikFmxW1XcspVpb9RvwTg== + dependencies: + "@types/node" "^9.3.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -4847,6 +4955,11 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" +parse-cache-control@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" + integrity sha1-juqz5U+laSD+Fro493+iGqzC104= + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -5042,6 +5155,13 @@ promise-to-callback@^1.0.0: is-fn "^1.0.0" set-immediate-shim "^1.0.1" +promise@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.2.tgz#9dcd0672192c589477d56891271bdc27547ae9f0" + integrity sha512-EIyzM39FpVOMbqgzEHhxdrEhtOSDOtjMZQ0M6iVfCE+kWNgCkAyOdnuCWqfmflylftfadU6FkiMgHZA2kUzwRw== + dependencies: + asap "~2.0.6" + prompt@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prompt/-/prompt-1.0.0.tgz#8e57123c396ab988897fb327fd3aedc3e735e4fe" @@ -5106,6 +5226,11 @@ qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" +qs@^6.4.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2" + integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA== + query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" @@ -5232,7 +5357,7 @@ readable-stream@^1.0.33: 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.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" dependencies: @@ -5350,18 +5475,41 @@ req-cwd@^1.0.1: dependencies: req-from "^1.0.1" +req-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" + integrity sha1-1AgrTURZgDZkD7c93qAe1T20nrw= + dependencies: + req-from "^2.0.0" + req-from@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" dependencies: resolve-from "^2.0.0" +req-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" + integrity sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA= + dependencies: + resolve-from "^3.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" dependencies: lodash "^4.13.1" +request-promise-native@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" + integrity sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU= + dependencies: + request-promise-core "1.1.1" + stealthy-require "^1.1.0" + tough-cookie ">=2.3.3" + request-promise@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" @@ -5371,7 +5519,7 @@ request-promise@^4.2.2: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.88.0: +request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.83.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" dependencies: @@ -5427,6 +5575,11 @@ resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -5698,6 +5851,14 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +sha1@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + integrity sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg= + dependencies: + charenc ">= 0.0.1" + crypt ">= 0.0.1" + sha3@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" @@ -5714,7 +5875,7 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" -shelljs@^0.7.4: +shelljs@^0.7.4, shelljs@^0.7.8: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" dependencies: @@ -5862,6 +6023,11 @@ solidity-docgen@^0.1.0: react-dom "^16.2.0" shelljs "^0.8.1" +solidity-parser-antlr@^0.2.10: + version "0.2.15" + resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.2.15.tgz#4be687a0a53da268c6a07398e0cfb3168896d610" + integrity sha512-EzRI8/TR/ljTXkZAyAjb0w4G20wH2XM7pcNf87ifdV825AbUv7DkY7HmiZCTj6NeKtIx8Y1s0NZWPbj+JTp8Zw== + 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" @@ -6193,6 +6359,22 @@ swarm-js@0.1.37: tar.gz "^1.0.5" xhr-request-promise "^0.1.2" +sync-request@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.0.0.tgz#db867eccc4ed31bbcb9fa3732393a3413da582ed" + integrity sha512-jGNIAlCi9iU4X3Dm4oQnNQshDD3h0/1A7r79LyqjbjUnj69sX6mShAXlhRXgImsfVKtTcnra1jfzabdZvp+Lmw== + dependencies: + http-response-object "^3.0.1" + sync-rpc "^1.2.1" + then-request "^6.0.0" + +sync-rpc@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.4.tgz#24bcbdb2ffcb98f23690c15b304660085cdd206c" + integrity sha512-Iug+t1ICVFenUcTnDu8WXFnT+k8IVoLKGh8VA3eXUtl2Rt9SjKX3YEv33OenABqpTPL9QEaHv1+CNn2LK8vMow== + dependencies: + get-port "^3.1.0" + table@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" @@ -6286,6 +6468,23 @@ text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +then-request@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.0.tgz#2cab198e48f2d8e79c8c1ed260198368a4a0bcba" + integrity sha512-xA+7uEMc+jsQIoyySJ93Ad08Kuqnik7u6jLS5hR91Z3smAoCfL3M8/MqMlobAa9gzBfO9pA88A/AntfepkkMJQ== + dependencies: + "@types/concat-stream" "^1.6.0" + "@types/form-data" "0.0.33" + "@types/node" "^8.0.0" + "@types/qs" "^6.2.31" + caseless "~0.12.0" + concat-stream "^1.6.0" + form-data "^2.2.0" + http-basic "^7.0.0" + http-response-object "^3.0.1" + promise "^8.0.0" + qs "^6.4.0" + 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" @@ -6438,9 +6637,10 @@ truffle-wallet-provider@0.0.5: web3 "^0.18.2" web3-provider-engine "^8.4.0" -truffle@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.0.tgz#2e4e2eedc5583ae38c7227585e5177d6360fbc6d" +truffle@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.4.tgz#fc68cb6a6a35b46a7ca69eca7b64d161b491db3d" + integrity sha512-pZYFbU10Hb6PiTalJm+dB6s1qIZjE5qc0ux5fIgQ7Nj24zDrlYmOYruP3yhuqywwzr3PUHGPxr6hXuje0BFYoA== dependencies: app-module-path "^2.2.0" mocha "^4.1.0" @@ -6502,6 +6702,11 @@ 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" + 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" From 957b9e38322e1ef218cc37db62b39ebaa873b68d Mon Sep 17 00:00:00 2001 From: Satyam Agrawal Date: Tue, 19 Feb 2019 01:58:13 +0530 Subject: [PATCH 112/119] EIP-1594/1644/1643/1410 implementation (#524) * EIP-1594/1644/1643 implementation * small fix * addition on delegate * minor fix * rename the verifyTransfer * accessing storage * fixed mapping storage read * minor fix * test fixes * fix to work with dev-3.0.0 * test fixes after merge * re-arrangement * improved balanceOfPartition * change the function name * change function name and return address as asc * fix tests --- contracts/interfaces/ISecurityToken.sol | 173 +++-- contracts/interfaces/ITransferManager.sol | 16 +- contracts/interfaces/token/IERC1594.sol | 28 + contracts/interfaces/token/IERC1643.sol | 18 + contracts/interfaces/token/IERC1644.sol | 28 + contracts/libraries/KindMath.sol | 54 +- contracts/libraries/TokenLib.sol | 94 ++- contracts/libraries/VolumeRestrictionLib.sol | 2 +- contracts/mocks/MockRedemptionManager.sol | 2 +- .../modules/Checkpoint/DividendCheckpoint.sol | 2 +- .../Checkpoint/ERC20DividendCheckpoint.sol | 2 +- .../Experimental/Burn/TrackedRedemption.sol | 2 +- .../Mixed/ScheduledCheckpoint.sol | 41 +- .../BlacklistTransferManager.sol | 36 +- .../TransferManager/KYCTransferManager.sol | 22 +- .../TransferManager/LockUpTransferManager.sol | 73 +- .../TransferManager/SignedTransferManager.sol | 46 +- .../Wallet/VestingEscrowWallet.sol | 2 +- contracts/modules/Module.sol | 4 +- .../GeneralPermissionManager.sol | 3 +- contracts/modules/STO/CappedSTO.sol | 4 +- contracts/modules/STO/DummySTO.sol | 5 +- contracts/modules/STO/PreSaleSTO.sol | 4 +- contracts/modules/STO/STO.sol | 2 +- contracts/modules/STO/USDTieredSTO.sol | 6 +- .../TransferManager/CountTransferManager.sol | 44 +- .../GeneralTransferManager.sol | 62 +- .../ManualApprovalTransferManager.sol | 54 +- .../PercentageTransferManager.sol | 49 +- .../TransferManager/TransferManager.sol | 9 + .../TransferManager/VolumeRestrictionTM.sol | 141 ++-- contracts/proxy/CappedSTOProxy.sol | 6 +- contracts/proxy/CountTransferManagerProxy.sol | 4 +- contracts/proxy/DummySTOProxy.sol | 6 +- .../proxy/ERC20DividendCheckpointProxy.sol | 6 +- .../proxy/EtherDividendCheckpointProxy.sol | 4 +- .../proxy/GeneralPermissionManagerProxy.sol | 5 +- .../proxy/GeneralTransferManagerProxy.sol | 4 +- .../ManualApprovalTransferManagerProxy.sol | 4 +- .../proxy/PercentageTransferManagerProxy.sol | 4 +- contracts/proxy/PreSaleSTOProxy.sol | 6 +- contracts/proxy/USDTieredSTOProxy.sol | 6 +- contracts/proxy/VestingEscrowWalletProxy.sol | 4 +- contracts/proxy/VolumeRestrictionTMProxy.sol | 4 +- .../Checkpoint/DividendCheckpointStorage.sol | 0 .../ERC20DividendCheckpointStorage.sol | 0 .../{ => storage}/modules/ModuleStorage.sol | 0 .../GeneralPermissionManagerStorage.sol | 0 .../modules/STO/CappedSTOStorage.sol | 0 .../modules/STO/DummySTOStorage.sol | 0 .../{ => storage}/modules/STO/ISTOStorage.sol | 0 .../modules/STO/PreSaleSTOStorage.sol | 0 .../{ => storage}/modules/STO/STOStorage.sol | 0 .../{ => modules/STO}/USDTieredSTOStorage.sol | 0 .../CountTransferManagerStorage.sol | 0 .../GeneralTransferManagerStorage.sol | 0 .../ManualApprovalTransferManagerStorage.sol | 0 .../PercentageTransferManagerStorage.sol | 0 .../VolumeRestrictionTMStorage.sol | 0 .../Wallet}/VestingEscrowWalletStorage.sol | 0 contracts/tokens/OZStorage.sol | 28 + contracts/tokens/STFactory.sol | 7 +- contracts/tokens/STGetter.sol | 210 ++++++ contracts/tokens/SecurityToken.sol | 688 ++++++++---------- contracts/tokens/SecurityTokenStorage.sol | 112 +++ docs/ethereum_status_codes.md | 46 ++ migrations/2_deploy_contracts.js | 12 +- module-labeling | 1 - package.json | 1 + scripts/compareStorageLayout.js | 48 +- test/b_capped_sto.js | 19 +- test/c_checkpoints.js | 52 +- test/d_count_transfer_manager.js | 37 +- test/e_erc20_dividends.js | 34 +- test/f_ether_dividends.js | 20 +- test/g_general_permission_manager.js | 14 +- test/h_general_transfer_manager.js | 16 +- test/helpers/createInstances.js | 12 +- test/i_Issuance.js | 12 +- test/j_manual_approval_transfer_manager.js | 50 +- test/k_module_registry.js | 6 +- test/l_percentage_transfer_manager.js | 22 +- test/m_presale_sto.js | 10 +- test/n_security_token_registry.js | 9 +- test/o_security_token.js | 577 ++++++++++++--- test/p_usd_tiered_sto.js | 11 +- test/q_usd_tiered_sto_sim.js | 10 +- test/r_concurrent_STO.js | 10 +- test/t_security_token_registry_proxy.js | 6 +- test/u_module_registry_proxy.js | 9 +- test/v_tracked_redemptions.js | 18 +- test/w_lockup_transfer_manager.js | 67 +- test/x_scheduled_checkpoints.js | 104 +-- test/y_volume_restriction_tm.js | 30 +- test/z_blacklist_transfer_manager.js | 20 +- .../z_fuzz_test_adding_removing_modules_ST.js | 11 +- ...zer_volumn_restriction_transfer_manager.js | 17 +- test/z_general_permission_manager_fuzzer.js | 10 +- test/z_vesting_escrow_wallet.js | 13 +- test/zb_signed_transfer_manager.js | 12 +- yarn.lock | 119 ++- 101 files changed, 2564 insertions(+), 1037 deletions(-) create mode 100644 contracts/interfaces/token/IERC1594.sol create mode 100644 contracts/interfaces/token/IERC1643.sol create mode 100644 contracts/interfaces/token/IERC1644.sol rename contracts/{ => storage}/modules/Checkpoint/DividendCheckpointStorage.sol (100%) rename contracts/{ => storage}/modules/Checkpoint/ERC20DividendCheckpointStorage.sol (100%) rename contracts/{ => storage}/modules/ModuleStorage.sol (100%) rename contracts/{ => storage}/modules/PermissionManager/GeneralPermissionManagerStorage.sol (100%) rename contracts/{ => storage}/modules/STO/CappedSTOStorage.sol (100%) rename contracts/{ => storage}/modules/STO/DummySTOStorage.sol (100%) rename contracts/{ => storage}/modules/STO/ISTOStorage.sol (100%) rename contracts/{ => storage}/modules/STO/PreSaleSTOStorage.sol (100%) rename contracts/{ => storage}/modules/STO/STOStorage.sol (100%) rename contracts/storage/{ => modules/STO}/USDTieredSTOStorage.sol (100%) rename contracts/{ => storage}/modules/TransferManager/CountTransferManagerStorage.sol (100%) rename contracts/storage/{ => modules/TransferManager}/GeneralTransferManagerStorage.sol (100%) rename contracts/{ => storage}/modules/TransferManager/ManualApprovalTransferManagerStorage.sol (100%) rename contracts/{ => storage}/modules/TransferManager/PercentageTransferManagerStorage.sol (100%) rename contracts/storage/{ => modules/TransferManager}/VolumeRestrictionTMStorage.sol (100%) rename contracts/storage/{ => modules/Wallet}/VestingEscrowWalletStorage.sol (100%) create mode 100644 contracts/tokens/OZStorage.sol create mode 100644 contracts/tokens/STGetter.sol create mode 100644 contracts/tokens/SecurityTokenStorage.sol create mode 100644 docs/ethereum_status_codes.md delete mode 100644 module-labeling diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index af0fb6a0c..7e9929908 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -18,14 +18,71 @@ interface ISecurityToken { event Approval(address indexed owner, address indexed spender, uint256 value); /** - * @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 - * @param _value Value of transfer - * @return bool + * @notice Transfers of securities may fail for a number of reasons. So this function will used to understand the + * cause of failure by getting the byte value. Which will be the ESC that follows the EIP 1066. ESC can be mapped + * with a reson string to understand the failure cause, table of Ethereum status code will always reside off-chain + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. + * @return bool It signifies whether the transaction will be executed or not. + * @return byte Ethereum status code (ESC) + * @return bytes32 Application specific reason code */ - function verifyTransfer(address _from, address _to, uint256 _value, bytes calldata _data) external returns(bool success); + function canTransfer(address _to, uint256 _value, bytes calldata _data) external view returns (bool, byte, bytes32); + + /** + * @notice Transfers of securities may fail for a number of reasons. So this function will used to understand the + * cause of failure by getting the byte value. Which will be the ESC that follows the EIP 1066. ESC can be mapped + * with a reson string to understand the failure cause, table of Ethereum status code will always reside off-chain + * @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 + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. + * @return bool It signifies whether the transaction will be executed or not. + * @return byte Ethereum status code (ESC) + * @return bytes32 Application specific reason code + */ + function canTransferFrom(address _from, address _to, uint256 _value, bytes calldata _data) external view returns (bool, byte, bytes32); + + /** + * @notice Used to attach a new document to the contract, or update the URI or hash of an existing attached document + * @dev Can only be executed by the owner of the contract. + * @param _name Name of the document. It should be unique always + * @param _uri Off-chain uri of the document from where it is accessible to investors/advisors to read. + * @param _documentHash hash (of the contents) of the document. + */ + function setDocument(bytes32 _name, string calldata _uri, bytes32 _documentHash) external; + + /** + * @notice Used to remove an existing document from the contract by giving the name of the document. + * @dev Can only be executed by the owner of the contract. + * @param _name Name of the document. It should be unique always + */ + function removeDocument(bytes32 _name) external; + + /** + * @notice Used to return the details of a document with a known name (`bytes32`). + * @param _name Name of the document + * @return string The URI associated with the document. + * @return bytes32 The hash (of the contents) of the document. + * @return uint256 the timestamp at which the document was last modified. + */ + function getDocument(bytes32 _name) external view returns (string memory, bytes32, uint256); + + /** + * @notice Used to retrieve a full list of documents attached to the smart contract. + * @return bytes32 List of all documents names present in the contract. + */ + function getAllDocuments() external view returns (bytes32[] memory); + + /** + * @notice In order to provide transparency over whether `controllerTransfer` / `controllerRedeem` are useable + * or not `isControllable` function will be used. + * @dev If `isControllable` returns `false` then it always return `false` and + * `controllerTransfer` / `controllerRedeem` will always revert. + * @return bool `true` when controller address is non-zero otherwise return `false`. + */ + function isControllable() external view returns (bool); /** * @notice Checks if an address is a module of certain type @@ -35,13 +92,15 @@ interface ISecurityToken { function isModule(address _module, uint8 _type) external view returns(bool); /** - * @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 - * @return success + * @notice This function must be called to increase the total supply (Corresponds to mint function of ERC20). + * @dev It only be called by the token issuer or the operator defined by the issuer. ERC1594 doesn't have + * have the any logic related to operator but its superset ERC1400 have the operator logic and this function + * is allowed to call by the operator. + * @param _tokenHolder The account that will receive the created tokens (account should be whitelisted or KYCed). + * @param _value The amount of tokens need to be issued + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. */ - function mint(address _investor, uint256 _value) external returns(bool success); + function issue(address _tokenHolder, uint256 _value, bytes calldata _data) external; /** * @notice Mints new tokens and assigns them to the target _investor. @@ -53,22 +112,28 @@ interface ISecurityToken { function mintWithData(address _investor, uint256 _value, bytes calldata _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 + * @notice This function redeem an amount of the token of a msg.sender. For doing so msg.sender may incentivize + * using different ways that could be implemented with in the `redeem` function definition. But those implementations + * are out of the scope of the ERC1594. + * @param _value The amount of tokens need to be redeemed + * @param _data The `bytes _data` it can be used in the token contract to authenticate the redemption. */ - function burnFromWithData(address _from, uint256 _value, bytes calldata _data) external; + function redeem(uint256 _value, bytes calldata _data) external; /** - * @notice Used to burn the securityToken - * @param _value No. of tokens to be burned - * @param _data Data to indicate validation + * @notice This function redeem an amount of the token of a msg.sender. For doing so msg.sender may incentivize + * using different ways that could be implemented with in the `redeem` function definition. But those implementations + * are out of the scope of the ERC1594. + * @dev It is analogy to `transferFrom` + * @param _tokenHolder The account whose tokens gets redeemed. + * @param _value The amount of tokens need to be redeemed + * @param _data The `bytes _data` it can be used in the token contract to authenticate the redemption. */ - function burnWithData(uint256 _value, bytes calldata _data) external; + function redeemFrom(address _tokenHolder, uint256 _value, bytes calldata _data) external; - event Minted(address indexed _to, uint256 _value); - event Burnt(address indexed _burner, uint256 _value); + // Issuance / Redemption Events + event Issued(address indexed _operator, address indexed _to, uint256 _value, bytes _data); + event Redeemed(address indexed _operator, address indexed _from, uint256 _value, bytes _data); /** * @notice Validate permissions with PermissionManager if it exists, If no Permission return false @@ -214,16 +279,7 @@ interface ISecurityToken { /** * @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[] calldata _investors, uint256[] calldata _values) external returns(bool success); + function freezeIssuance() external; /** * @notice Attachs a module to the SecurityToken @@ -282,23 +338,33 @@ interface ISecurityToken { 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 + * @notice This function allows an authorised address to transfer tokens between any two token holders. + * The transfer must still respect the balances of the token holders (so the transfer must be for at most + * `balanceOf(_from)` tokens) and potentially also need to respect other transfer restrictions. + * @dev This function can only be executed by the `controller` address. + * @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 + * @param _data data to validate the transfer. (It is not used in this reference implementation + * because use of `_data` parameter is implementation specific). + * @param _operatorData data attached to the transfer by controller to emit in event. (It is more like a reason string + * for calling this function (aka force transfer) which provides the transparency on-chain). */ - function forceTransfer(address _from, address _to, uint256 _value, bytes calldata _data, bytes calldata _log) external; + function controllerTransfer(address _from, address _to, uint256 _value, bytes calldata _data, bytes calldata _operatorData) 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 + * @notice This function allows an authorised address to redeem tokens for any token holder. + * The redemption must still respect the balances of the token holder (so the redemption must be for at most + * `balanceOf(_tokenHolder)` tokens) and potentially also need to respect other transfer restrictions. + * @dev This function can only be executed by the `controller` address. + * @param _tokenHolder The account whose tokens will be redeemed. + * @param _value uint256 the amount of tokens need to be redeemed. + * @param _data data to validate the transfer. (It is not used in this reference implementation + * because use of `_data` parameter is implementation specific). + * @param _operatorData data attached to the transfer by controller to emit in event. (It is more like a reason string + * for calling this function (aka force transfer) which provides the transparency on-chain). */ - function forceBurn(address _from, uint256 _value, bytes calldata _data, bytes calldata _log) external; + function controllerRedeem(address _tokenHolder, uint256 _value, bytes calldata _data, bytes calldata _operatorData) external; /** * @notice Used by the issuer to permanently disable controller functionality @@ -328,7 +394,7 @@ interface ISecurityToken { * @param _data data to indicate validation * @return bool success */ - function transferWithData(address _to, uint256 _value, bytes calldata _data) external returns(bool success); + function transferWithData(address _to, uint256 _value, bytes calldata _data) external; /** * @notice Overloaded version of the transferFrom function @@ -338,11 +404,20 @@ interface ISecurityToken { * @param _data data to indicate validation * @return bool success */ - function transferFromWithData(address _from, address _to, uint256 _value, bytes calldata _data) external returns(bool); + function transferFromWithData(address _from, address _to, uint256 _value, bytes calldata _data) external; /** * @notice Provides the granularity of the token * @return uint256 */ function granularity() external view returns(uint256); + + /** + * @notice A security token issuer can specify that issuance has finished for the token + * (i.e. no new tokens can be minted or issued). + * @dev If a token returns FALSE for `isIssuable()` then it MUST always return FALSE in the future. + * If a token returns FALSE for `isIssuable()` then it MUST never allow additional tokens to be issued. + * @return bool `true` signifies the minting is allowed. While `false` denotes the end of minting + */ + function isIssuable() external view returns (bool); } diff --git a/contracts/interfaces/ITransferManager.sol b/contracts/interfaces/ITransferManager.sol index 1e7dd0f2c..3045b3579 100644 --- a/contracts/interfaces/ITransferManager.sol +++ b/contracts/interfaces/ITransferManager.sol @@ -4,10 +4,24 @@ pragma solidity ^0.5.0; * @title Interface to be implemented by all Transfer Manager modules */ interface ITransferManager { + // If verifyTransfer returns: + // FORCE_VALID, the transaction will always be valid, regardless of other TM results + // INVALID, then the transfer should not be allowed regardless of other TM results + // VALID, then the transfer is valid for this TM + // NA, then the result from this TM is ignored enum Result {INVALID, NA, VALID, FORCE_VALID} /** * @notice Determines if the transfer between these two accounts can happen */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes calldata _data, bool _isTransfer) external returns(Result); + function executeTransfer(address _from, address _to, uint256 _amount, bytes calldata _data) external returns(Result); + + function verifyTransfer(address _from, address _to, uint256 _amount, bytes calldata _data) external view returns(Result, bytes32); + + /** + * @notice return the amount of tokens for a given user as per the partition + * @param _owner Whom token amount need to query + * @param _partition Identifier + */ + function getTokensByPartition(address _owner, bytes32 _partition) external view returns(uint256); } diff --git a/contracts/interfaces/token/IERC1594.sol b/contracts/interfaces/token/IERC1594.sol new file mode 100644 index 000000000..00e1e4d36 --- /dev/null +++ b/contracts/interfaces/token/IERC1594.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.5.0; + +/** + * @title Standard Interface of ERC1594 + */ +interface IERC1594 { + + // Transfers + function transferWithData(address _to, uint256 _value, bytes calldata _data) external; + function transferFromWithData(address _from, address _to, uint256 _value, bytes calldata _data) external; + + // Token Issuance + function isIssuable() external view returns (bool); + function issue(address _tokenHolder, uint256 _value, bytes calldata _data) external; + + // Token Redemption + function redeem(uint256 _value, bytes calldata _data) external; + function redeemFrom(address _tokenHolder, uint256 _value, bytes calldata _data) external; + + // Transfer Validity + function canTransfer(address _to, uint256 _value, bytes calldata _data) external view returns (bool, byte, bytes32); + function canTransferFrom(address _from, address _to, uint256 _value, bytes calldata _data) external view returns (bool, byte, bytes32); + + // Issuance / Redemption Events + event Issued(address indexed _operator, address indexed _to, uint256 _value, bytes _data); + event Redeemed(address indexed _operator, address indexed _from, uint256 _value, bytes _data); + +} \ No newline at end of file diff --git a/contracts/interfaces/token/IERC1643.sol b/contracts/interfaces/token/IERC1643.sol new file mode 100644 index 000000000..90ff408ce --- /dev/null +++ b/contracts/interfaces/token/IERC1643.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.5.0; + +// @title IERC1643 Document Management (part of the ERC1400 Security Token Standards) +/// @dev See https://github.com/SecurityTokenStandard/EIP-Spec + +interface IERC1643 { + + // Document Management + //function getDocument(bytes32 _name) external view returns (string memory, bytes32, uint256); + function setDocument(bytes32 _name, string calldata _uri, bytes32 _documentHash) external; + function removeDocument(bytes32 _name) external; + //function getAllDocuments() external view returns (bytes32[] memory); + + // Document Events + event DocumentRemoved(bytes32 indexed _name, string _uri, bytes32 _documentHash); + event DocumentUpdated(bytes32 indexed _name, string _uri, bytes32 _documentHash); + +} \ No newline at end of file diff --git a/contracts/interfaces/token/IERC1644.sol b/contracts/interfaces/token/IERC1644.sol new file mode 100644 index 000000000..d03e1cf30 --- /dev/null +++ b/contracts/interfaces/token/IERC1644.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.5.0; + +interface IERC1644 { + + // Controller Operation + function isControllable() external view returns (bool); + function controllerTransfer(address _from, address _to, uint256 _value, bytes calldata _data, bytes calldata _operatorData) external; + function controllerRedeem(address _tokenHolder, uint256 _value, bytes calldata _data, bytes calldata _operatorData) external; + + // Controller Events + event ControllerTransfer( + address _controller, + address indexed _from, + address indexed _to, + uint256 _value, + bytes _data, + bytes _operatorData + ); + + event ControllerRedemption( + address _controller, + address indexed _tokenHolder, + uint256 _value, + bytes _data, + bytes _operatorData + ); + +} \ No newline at end of file diff --git a/contracts/libraries/KindMath.sol b/contracts/libraries/KindMath.sol index 00810abb1..e9de30c65 100644 --- a/contracts/libraries/KindMath.sol +++ b/contracts/libraries/KindMath.sol @@ -1,52 +1,48 @@ pragma solidity ^0.5.0; -// Copied from OpenZeppelin and modified to be friendlier - /** * @title KindMath - * @dev Math operations with safety checks that throw on error + * @notice ref. https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol + * @dev Math operations with safety checks that returns boolean */ library KindMath { + /** - * @dev Multiplies two numbers, throws on overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns(uint256 c) { + * @dev Multiplies two numbers, return false on overflow. + */ + function checkMul(uint256 a, uint256 b) internal pure returns (bool) { // Gas optimization: this is cheaper than requireing '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; + return true; } - c = a * b; - require(c / a == b, "mul overflow"); - return c; - } - - /** - * @dev Integer division of two numbers, truncating the quotient. - */ - function div(uint256 a, uint256 b) internal pure returns(uint256) { - // require(b > 0); // Solidity automatically throws when dividing by 0 - // uint256 c = a / b; - // require(a == b * c + a % b); // There is no case in which this doesn't hold - return a / b; + uint256 c = a * b; + if (c / a == b) + return true; + else + return false; } /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + * @dev Subtracts two numbers, return false on overflow (i.e. if subtrahend is greater than minuend). */ - function sub(uint256 a, uint256 b) internal pure returns(uint256) { - require(b <= a, "sub overflow"); - return a - b; + function checkSub(uint256 a, uint256 b) internal pure returns (bool) { + if (b <= a) + return true; + else + return false; } /** - * @dev Adds two numbers, throws on overflow. + * @dev Adds two numbers, return false on overflow. */ - function add(uint256 a, uint256 b) internal pure returns(uint256 c) { - c = a + b; - require(c >= a, "add overflow"); - return c; + function checkAdd(uint256 a, uint256 b) internal pure returns (bool) { + uint256 c = a + b; + if (c < a) + return false; + else + return true; } } diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index bbbf78bb9..b432f8bb4 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -1,33 +1,19 @@ pragma solidity ^0.5.0; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../interfaces/IPoly.sol"; import "../interfaces/IDataStore.sol"; +import "../tokens/SecurityTokenStorage.sol"; +import "../interfaces/ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../modules/PermissionManager/IPermissionManager.sol"; library TokenLib { + using SafeMath for uint256; bytes32 internal constant WHITELIST = "WHITELIST"; bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) - // Struct for module data - struct ModuleData { - bytes32 name; - address module; - address moduleFactory; - bool isArchived; - uint8[] moduleTypes; - uint256[] moduleIndexes; - uint256 nameIndex; - bytes32 label; - } - - // Structures to maintain checkpoints of balances for governance / dividends - struct Checkpoint { - uint256 checkpointId; - uint256 value; - } - // Emit when Module is archived from the SecurityToken event ModuleArchived(uint8[] _types, address _module); // Emit when Module is unarchived from the SecurityToken @@ -42,7 +28,7 @@ library TokenLib { * @param _moduleData Storage data * @param _module Address of module to archive */ - function archiveModule(ModuleData storage _moduleData, address _module) public { + function archiveModule(SecurityTokenStorage.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*/ @@ -55,7 +41,7 @@ library TokenLib { * @param _moduleData Storage data * @param _module Address of module to unarchive */ - function unarchiveModule(ModuleData storage _moduleData, address _module) public { + function unarchiveModule(SecurityTokenStorage.ModuleData storage _moduleData, address _module) public { require(_moduleData.isArchived, "Module unarchived"); /*solium-disable-next-line security/no-block-members*/ emit ModuleUnarchived(_moduleData.moduleTypes, _module); @@ -69,7 +55,7 @@ library TokenLib { function removeModule( address _module, mapping(uint8 => address[]) storage _modules, - mapping(address => ModuleData) storage _modulesToData, + mapping(address => SecurityTokenStorage.ModuleData) storage _modulesToData, mapping(bytes32 => address[]) storage _names ) public @@ -104,7 +90,7 @@ library TokenLib { uint8 _type, uint256 _index, mapping(uint8 => address[]) storage _modules, - mapping(address => ModuleData) storage _modulesToData + mapping(address => SecurityTokenStorage.ModuleData) storage _modulesToData ) internal { @@ -134,7 +120,7 @@ library TokenLib { uint256 _change, bool _increase, address _polyToken, - mapping(address => ModuleData) storage _modulesToData + mapping(address => SecurityTokenStorage.ModuleData) storage _modulesToData ) public { @@ -158,7 +144,7 @@ library TokenLib { * @param _currentValue is the Current value of checkpoint * @return uint256 */ - function getValueAt(Checkpoint[] storage _checkpoints, uint256 _checkpointId, uint256 _currentValue) public view returns(uint256) { + function getValueAt(SecurityTokenStorage.Checkpoint[] storage _checkpoints, uint256 _checkpointId, uint256 _currentValue) public view returns(uint256) { //Checkpoint id 0 is when the token is first created - everyone has a zero balance if (_checkpointId == 0) { return 0; @@ -197,7 +183,7 @@ library TokenLib { * @param _checkpoints is the affected checkpoint object array * @param _newValue is the new value that needs to be stored */ - function adjustCheckpoints(TokenLib.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public { + function adjustCheckpoints(SecurityTokenStorage.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public { //No checkpoints set yet if (_currentCheckpointId == 0) { return; @@ -207,7 +193,7 @@ library TokenLib { return; } //New checkpoint, so record balance - _checkpoints.push(TokenLib.Checkpoint({checkpointId: _currentCheckpointId, value: _newValue})); + _checkpoints.push(SecurityTokenStorage.Checkpoint({checkpointId: _currentCheckpointId, value: _newValue})); } /** @@ -253,6 +239,60 @@ library TokenLib { return _holderCount; } + /** + * @notice Validate transfer with TransferManager module if it exists + * @dev TransferManager module has a key of 2 + * @param from sender of transfer + * @param to receiver of transfer + * @param value value of transfer + * @param data data to indicate validation + * @param modules Array of addresses for transfer managers + * @param modulesToData Mapping of the modules details + * @param transfersFrozen whether the transfer are frozen or not. + * @return bool + */ + function verifyTransfer( + address[] storage modules, + mapping(address => SecurityTokenStorage.ModuleData) storage modulesToData, + address from, + address to, + uint256 value, + bytes memory data, + bool transfersFrozen + ) + public + view + returns(bool, bytes32) + { + if (!transfersFrozen) { + bool isInvalid = false; + bool isValid = false; + bool isForceValid = false; + // Use the local variables to avoid the stack too deep error + transfersFrozen = false; // bool unarchived = false; + bytes32 appCode; + for (uint256 i = 0; i < modules.length; i++) { + if (!modulesToData[modules[i]].isArchived) { + transfersFrozen = true; + (ITransferManager.Result valid, bytes32 reason) = ITransferManager(modules[i]).verifyTransfer(from, to, value, data); + if (valid == ITransferManager.Result.INVALID) { + isInvalid = true; + appCode = reason; + } else if (valid == ITransferManager.Result.VALID) { + isValid = true; + } else if (valid == ITransferManager.Result.FORCE_VALID) { + isForceValid = true; + } + } + } + // If no unarchived modules, return true by default + // Use the local variables to avoid the stack too deep error + isValid = transfersFrozen ? (isForceValid ? true : (isInvalid ? false : isValid)) : true; + return (isValid, isValid ? bytes32(hex"51"): appCode); + } + return (false, bytes32(hex"54")); + } + function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } diff --git a/contracts/libraries/VolumeRestrictionLib.sol b/contracts/libraries/VolumeRestrictionLib.sol index 3b3a05da2..589256de1 100644 --- a/contracts/libraries/VolumeRestrictionLib.sol +++ b/contracts/libraries/VolumeRestrictionLib.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../storage/VolumeRestrictionTMStorage.sol"; +import "../storage/modules/TransferManager/VolumeRestrictionTMStorage.sol"; library VolumeRestrictionLib { diff --git a/contracts/mocks/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol index f5d117497..6ba5994d4 100644 --- a/contracts/mocks/MockRedemptionManager.sol +++ b/contracts/mocks/MockRedemptionManager.sol @@ -35,7 +35,7 @@ contract MockRedemptionManager is TrackedRedemption { 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, ""); + ISecurityToken(securityToken).redeem(_value, ""); /*solium-disable-next-line security/no-block-members*/ emit RedeemedTokenByOwner(msg.sender, address(this), _value, now); } diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index e4e0d7dfb..ebb4e944e 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -8,7 +8,7 @@ pragma solidity ^0.5.0; import "./ICheckpoint.sol"; -import "./DividendCheckpointStorage.sol"; +import "../../storage/modules/Checkpoint/DividendCheckpointStorage.sol"; import "../Module.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/math/Math.sol"; diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol index a672b88ef..68d24c38e 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpoint.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.0; import "./DividendCheckpoint.sol"; -import "./ERC20DividendCheckpointStorage.sol"; +import "../../storage/modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; import "../../interfaces/IOwnable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/modules/Experimental/Burn/TrackedRedemption.sol b/contracts/modules/Experimental/Burn/TrackedRedemption.sol index e6af32d43..4f6c1d4ce 100644 --- a/contracts/modules/Experimental/Burn/TrackedRedemption.sol +++ b/contracts/modules/Experimental/Burn/TrackedRedemption.sol @@ -34,7 +34,7 @@ contract TrackedRedemption is IBurn, Module { * @param _value The number of tokens to redeem */ function redeemTokens(uint256 _value) public { - ISecurityToken(securityToken).burnFromWithData(msg.sender, _value, ""); + ISecurityToken(securityToken).redeemFrom(msg.sender, _value, ""); redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); /*solium-disable-next-line security/no-block-members*/ emit Redeemed(msg.sender, _value); diff --git a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol index f0d1cbc9c..64301c681 100644 --- a/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol +++ b/contracts/modules/Experimental/Mixed/ScheduledCheckpoint.sol @@ -79,25 +79,39 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { /** * @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( + function executeTransfer( address, /* _from */ address, /* _to */ uint256, /* _amount */ - bytes calldata, /* _data */ - bool _isTransfer + bytes calldata /* _data */ ) - external + external + onlySecurityToken returns(Result) { - require(_isTransfer == false || msg.sender == securityToken, "Sender is not owner"); - if (paused || !_isTransfer) { - return Result.NA; + if (!paused) { + _updateAll(); } - _updateAll(); - return Result.NA; + return (Result.NA); + } + + /** + * @notice Used to create checkpoints that correctly reflect balances + * @return always returns Result.NA + */ + function verifyTransfer( + address, /* _from */ + address, /* _to */ + uint256, /* _amount */ + bytes memory /* _data */ + ) + public + view + returns(Result, bytes32) + { + return (Result.NA, bytes32(0)); } /** @@ -150,6 +164,13 @@ contract ScheduledCheckpoint is ICheckpoint, TransferManager { } } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + /** * @notice Return the permissions flag that are associated with CountTransferManager */ diff --git a/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol b/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol index 68da9084b..059588a6e 100644 --- a/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/BlacklistTransferManager.sol @@ -94,7 +94,29 @@ contract BlacklistTransferManager is TransferManager { * 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 memory/* _data */, bool /* _isTransfer */) public returns(Result) { + function executeTransfer(address _from, address _to, uint256 _amount, bytes calldata _data) external returns(Result) { + (Result success, ) = verifyTransfer(_from, _to, _amount, _data); + return success; + } + + + /** + * @notice Used to verify the transfer transaction (View) + * @param _from Address of the sender + * @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 memory/* _data */ + ) + public + view + returns(Result, bytes32) + { if (!paused) { if (investorToBlacklist[_from].length != 0) { for (uint256 i = 0; i < investorToBlacklist[_from].length; i++) { @@ -109,15 +131,16 @@ contract BlacklistTransferManager is TransferManager { uint256 repeater = (now.sub(startTimeTemp)).div(repeatPeriodTimeTemp); /*solium-disable-next-line security/no-block-members*/ if (startTimeTemp.add(repeatPeriodTimeTemp.mul(repeater)) <= now && endTimeTemp.add(repeatPeriodTimeTemp.mul(repeater)) >= now) { - return Result.INVALID; + return (Result.INVALID, bytes32(uint256(address(this)) << 96)); } } } } } - return Result.NA; + return (Result.NA, bytes32(0)); } + /** * @notice Used to add the blacklist type * @param _startTime Start date of the blacklist type @@ -388,6 +411,13 @@ contract BlacklistTransferManager is TransferManager { return allBlacklists; } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + /** * @notice Return the permissions flag that are associated with blacklist transfer manager */ diff --git a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol index a4bd779e0..a2741d346 100644 --- a/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/KYCTransferManager.sol @@ -35,15 +35,20 @@ contract KYCTransferManager is TransferManager { return bytes4(0); } - function verifyTransfer(address /*_from*/, address _to, uint256 /*_amount*/, bytes memory /* _data */, bool /* _isTransfer */) - public + function executeTransfer(address _from, address _to, uint256 _amount, bytes calldata _data) + external returns (Result) { + (Result success,)= verifyTransfer(_from, _to, _amount, _data); + return success; + } + + function verifyTransfer(address /*_from*/, address _to, uint256 /*_amount*/, bytes memory /* _data */) public view returns(Result, bytes32) { if (!paused && checkKYC(_to)) { - return Result.VALID; + return (Result.VALID, bytes32(uint256(address(this)) << 96)); } - return Result.NA; - } + return (Result.NA, bytes32(0)); + } function modifyKYC( address _investor, bool _kycStatus) public withPerm(KYC_PROVIDER) { _modifyKYC(_investor, _kycStatus); @@ -95,4 +100,11 @@ contract KYCTransferManager is TransferManager { return bytes32(keccak256(abi.encodePacked(KYC_NUMBER, _identity))); } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + } diff --git a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol index bcb60b149..5519e44b6 100644 --- a/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/LockUpTransferManager.sol @@ -2,6 +2,7 @@ pragma solidity ^0.5.0; import "../../TransferManager/TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "openzeppelin-solidity/contracts/math/Math.sol"; contract LockUpTransferManager is TransferManager { @@ -74,15 +75,34 @@ contract LockUpTransferManager is TransferManager { * @param _from Address of the sender * @param _amount The amount of tokens to transfer */ - function verifyTransfer(address _from, address /* _to*/, uint256 _amount, bytes memory /* _data */, bool /*_isTransfer*/) public returns(Result) { + function executeTransfer(address _from, address _to, uint256 _amount, bytes calldata _data) external returns(Result) { + (Result success,) = verifyTransfer(_from, _to, _amount, _data); + return success; + } + + /** @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 memory /* _data */ + ) + public + view + returns(Result, bytes32) + { // 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; + return (Result.NA, bytes32(0)); } + /** * @notice Use to add the new lockup type * @param _lockupAmount Amount of tokens that need to lock. @@ -133,7 +153,7 @@ contract LockUpTransferManager is TransferManager { _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" + "Length mismatch" ); for (uint256 i = 0; i < _lockupNames.length; i++) { _addNewLockUpType( @@ -235,7 +255,7 @@ contract LockUpTransferManager is TransferManager { _userAddresses.length == _startTimes.length && /*solium-disable-line operator-whitespace*/ _userAddresses.length == _lockupAmounts.length && _userAddresses.length == _lockupNames.length, - "Input array length mismatch" + "Length mismatch" ); for (uint256 i = 0; i < _userAddresses.length; i++) { _addNewLockUpToUser(_userAddresses[i], _lockupAmounts[i], _startTimes[i], _lockUpPeriodsSeconds[i], _releaseFrequenciesSeconds[i], _lockupNames[i]); @@ -275,7 +295,7 @@ contract LockUpTransferManager is TransferManager { * @param _lockupNames Array of the names of the lockup that needs to be removed. */ function removeLockUpFromUserMulti(address[] calldata _userAddresses, bytes32[] calldata _lockupNames) external withPerm(ADMIN) { - require(_userAddresses.length == _lockupNames.length, "Array length mismatch"); + require(_userAddresses.length == _lockupNames.length, "Length mismatch"); for (uint256 i = 0; i < _userAddresses.length; i++) { _removeLockUpFromUser(_userAddresses[i], _lockupNames[i]); } @@ -331,7 +351,7 @@ contract LockUpTransferManager is TransferManager { _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" + "Length mismatch" ); for (uint256 i = 0; i < _lockupNames.length; i++) { _modifyLockUpType( @@ -373,7 +393,7 @@ contract LockUpTransferManager is TransferManager { * @return address List of users associated with the blacklist */ function getListOfAddresses(bytes32 _lockupName) external view returns(address[] memory) { - require(lockups[_lockupName].startTime != 0, "Blacklist type doesn't exist"); + require(lockups[_lockupName].startTime != 0, "Invalid blacklist"); return lockupToUsers[_lockupName]; } @@ -418,14 +438,14 @@ contract LockUpTransferManager is TransferManager { * @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) { + function _checkIfValidTransfer(address _userAddress, uint256 _amount) internal view returns (Result, bytes32) { uint256 totalRemainingLockedAmount = getLockedTokenToUser(_userAddress); // Present balance of the user uint256 currentBalance = IERC20(securityToken).balanceOf(_userAddress); if ((currentBalance.sub(_amount)) >= totalRemainingLockedAmount) { - return Result.NA; + return (Result.NA, bytes32(0)); } - return Result.INVALID; + return (Result.INVALID, bytes32(uint256(address(this)) << 96)); } /** @@ -450,8 +470,8 @@ contract LockUpTransferManager is TransferManager { } 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"); + require(lockups[_lockupName].startTime != 0, "Invalid lockup"); + require(lockupToUsers[_lockupName].length == 0, "Not empty"); // delete lockup type delete(lockups[_lockupName]); uint256 i = 0; @@ -512,7 +532,7 @@ contract LockUpTransferManager is TransferManager { require(_lockupName != bytes32(0), "Invalid lockup name"); require( userToLockups[_userAddress][userToLockupIndex[_userAddress][_lockupName]] == _lockupName, - "User not assosicated with given lockup" + "Not empty" ); // delete the user from the lockup type @@ -613,11 +633,32 @@ contract LockUpTransferManager is TransferManager { internal pure { - require(_lockUpPeriodSeconds != 0, "lockUpPeriodSeconds cannot be zero"); - require(_releaseFrequencySeconds != 0, "releaseFrequencySeconds cannot be zero"); - require(_lockupAmount != 0, "lockupAmount cannot be zero"); + require( + _lockUpPeriodSeconds != 0 && + _releaseFrequencySeconds != 0 && + _lockupAmount != 0, + "Cannot be zero" + ); } + /** + * @notice return the amount of tokens for a given user as per the partition + * @param _owner Whom token amount need to query + * @param _partition Identifier + */ + function getTokensByPartition(address _owner, bytes32 _partition) external view returns(uint256){ + uint256 _currentBalance = IERC20(securityToken).balanceOf(_owner); + if (_partition == LOCKED) { + return Math.min(getLockedTokenToUser(_owner), _currentBalance); + } else if (_partition == UNLOCKED) { + if (_currentBalance < getLockedTokenToUser(_owner)) { + return 0; + } + return _currentBalance.sub(getLockedTokenToUser(_owner)); + } + return 0; + } + /** * @notice This function returns the signature of configure function */ diff --git a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index 69fed8036..bcf42edb8 100644 --- a/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -86,17 +86,33 @@ contract SignedTransferManager is TransferManager { * @param _to address transfer to * @param _amount transfer amount * @param _data signature - * @param _isTransfer bool value of isTransfer * Sig needs to be valid (not used or deemed as invalid) * Signer needs to be in the signers mapping */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes memory _data , bool _isTransfer) public returns(Result) { - if (!paused) { + function executeTransfer(address _from, address _to, uint256 _amount, bytes calldata _data) external onlySecurityToken returns(Result) { + (Result success, ) = verifyTransfer(_from, _to, _amount, _data); + if (success == Result.VALID) { + bytes memory signature; + (,,,signature) = abi.decode(_data, (address, uint256, uint256, bytes)); + _invalidateSignature(signature); + } + return success; + } - require (_isTransfer == false || msg.sender == securityToken, "Sender is not ST"); + /** + * @notice allow verify transfer with signature + * @param _from address transfer from + * @param _to address transfer to + * @param _amount transfer amount + * @param _data signature + * Sig needs to be valid (not used or deemed as invalid) + * Signer needs to be in the signers mapping + */ + function verifyTransfer(address _from, address _to, uint256 _amount, bytes memory _data) public view returns(Result, bytes32) { + if (!paused) { if (_data.length == 0) - return Result.NA; + return (Result.NA, bytes32(0)); address targetAddress; uint256 nonce; @@ -105,19 +121,16 @@ contract SignedTransferManager is TransferManager { (targetAddress, nonce, expiry, signature) = abi.decode(_data, (address, uint256, uint256, bytes)); if (address(this) != targetAddress || signature.length == 0 || _checkSignatureIsInvalid(signature) || expiry < now) - return Result.NA; + return (Result.NA, bytes32(0)); bytes32 hash = keccak256(abi.encodePacked(targetAddress, nonce, expiry, _from, _to, _amount)); address signer = hash.toEthSignedMessageHash().recover(signature); - if (!_checkSigner(signer)) { - return Result.NA; - } else if(_isTransfer) { - _invalidateSignature(signature); - } - return Result.VALID; + if (!_checkSigner(signer)) + return (Result.NA, bytes32(0)); + return (Result.VALID, bytes32(uint256(address(this)) << 96)); } - return Result.NA; + return (Result.NA, bytes32(0)); } /** @@ -156,6 +169,13 @@ contract SignedTransferManager is TransferManager { return allPermissions; } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256) { + return 0; + } + function _checkSignatureIsInvalid(bytes memory _data) internal view returns(bool) { IDataStore dataStore = IDataStore(ISecurityToken(securityToken).dataStore()); return dataStore.getBool(keccak256(abi.encodePacked(INVALID_SIG, _data))); diff --git a/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol index e0231aacd..3dc85999d 100644 --- a/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol +++ b/contracts/modules/Experimental/Wallet/VestingEscrowWallet.sol @@ -1,7 +1,7 @@ pragma solidity ^0.5.0; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../../../storage/VestingEscrowWalletStorage.sol"; +import "../../../storage/modules/Wallet/VestingEscrowWalletStorage.sol"; import "./IWallet.sol"; /** diff --git a/contracts/modules/Module.sol b/contracts/modules/Module.sol index 4ed977d54..b0d233201 100644 --- a/contracts/modules/Module.sol +++ b/contracts/modules/Module.sol @@ -1,12 +1,12 @@ pragma solidity ^0.5.0; -import "./ModuleStorage.sol"; import "../interfaces/IModule.sol"; import "../interfaces/IDataStore.sol"; import "../interfaces/ISecurityToken.sol"; import "../interfaces/ICheckPermission.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; +import "../storage/modules/ModuleStorage.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; /** * @title Interface that any module contract should implement diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 39b09050b..7a37476b3 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -2,7 +2,8 @@ pragma solidity ^0.5.0; import "./IPermissionManager.sol"; import "../Module.sol"; -import "./GeneralPermissionManagerStorage.sol"; +import "../../storage/modules/PermissionManager/GeneralPermissionManagerStorage.sol"; +import "../../interfaces/ISecurityToken.sol"; /** * @title Permission Manager module for core permissioning functionality diff --git a/contracts/modules/STO/CappedSTO.sol b/contracts/modules/STO/CappedSTO.sol index 4cec5d9c9..69cd1cfe3 100644 --- a/contracts/modules/STO/CappedSTO.sol +++ b/contracts/modules/STO/CappedSTO.sol @@ -3,7 +3,7 @@ pragma solidity ^0.5.0; import "./STO.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./CappedSTOStorage.sol"; +import "../../storage/modules/STO/CappedSTOStorage.sol"; /** * @title STO module for standard capped crowdsale @@ -221,7 +221,7 @@ contract CappedSTO is CappedSTOStorage, STO, ReentrancyGuard { * @param _tokenAmount Number of tokens to be emitted */ function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal { - require(ISecurityToken(securityToken).mint(_beneficiary, _tokenAmount), "Error in minting the tokens"); + ISecurityToken(securityToken).issue(_beneficiary, _tokenAmount, ""); } /** diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index f562be892..f49aee7ae 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -1,7 +1,8 @@ pragma solidity ^0.5.0; import "./STO.sol"; -import "./DummySTOStorage.sol"; +import "../../interfaces/ISecurityToken.sol"; +import "../../storage/modules/STO/DummySTOStorage.sol"; /** * @title STO module for sample implementation of a different crowdsale module @@ -48,7 +49,7 @@ contract DummySTO is DummySTOStorage, STO { require(!paused, "Should not be paused"); require(_amount > 0, "Amount should be greater than 0"); require(_canBuy(_investor), "Unauthorized"); - ISecurityToken(securityToken).mint(_investor, _amount); + ISecurityToken(securityToken).issue(_investor, _amount, ""); if (investors[_investor] == 0) { investorCount = investorCount + 1; } diff --git a/contracts/modules/STO/PreSaleSTO.sol b/contracts/modules/STO/PreSaleSTO.sol index 98fd033f3..147c85b8d 100644 --- a/contracts/modules/STO/PreSaleSTO.sol +++ b/contracts/modules/STO/PreSaleSTO.sol @@ -2,7 +2,7 @@ pragma solidity ^0.5.0; import "./STO.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./PreSaleSTOStorage.sol"; +import "../../storage/modules/STO/PreSaleSTOStorage.sol"; /** * @title STO module for private presales @@ -79,7 +79,7 @@ contract PreSaleSTO is PreSaleSTOStorage, STO { require(now <= endTime, "Already passed Endtime"); require(_amount > 0, "No. of tokens provided should be greater the zero"); require(_canBuy(_investor), "Unauthorized"); - ISecurityToken(securityToken).mint(_investor, _amount); + ISecurityToken(securityToken).issue(_investor, _amount, ""); if (investors[_investor] == uint256(0)) { investorCount = investorCount.add(1); } diff --git a/contracts/modules/STO/STO.sol b/contracts/modules/STO/STO.sol index ae69238fd..7cc72f135 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -3,7 +3,7 @@ pragma solidity ^0.5.0; import "../../Pausable.sol"; import "../Module.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; -import "./STOStorage.sol"; +import "../../storage/modules/STO/STOStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "../../interfaces/ISTO.sol"; diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 6de21c48d..421aa978e 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -5,7 +5,7 @@ import "../../interfaces/IOracle.sol"; import "../../RegistryUpdater.sol"; import "../../libraries/DecimalMath.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "../../storage/USDTieredSTOStorage.sol"; +import "../../storage/modules/STO/USDTieredSTOStorage.sol"; /** * @title STO module for standard capped crowdsale @@ -266,7 +266,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { tiers[i].mintedTotal = tiers[i].tokenTotal; } } - require(ISecurityToken(securityToken).mint(reserveWallet, tempReturned), "Minting Failed"); + ISecurityToken(securityToken).issue(reserveWallet, tempReturned, ""); emit ReserveTokenMint(msg.sender, reserveWallet, tempReturned, currentTier); finalAmountReturned = tempReturned; totalTokensSold = tempSold; @@ -539,7 +539,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { purchasedTokens = maximumTokens; } if (purchasedTokens > 0) { - require(ISecurityToken(securityToken).mint(_beneficiary, purchasedTokens), "Mint failed"); + ISecurityToken(securityToken).issue(_beneficiary, purchasedTokens, ""); emit TokenPurchase(msg.sender, _beneficiary, purchasedTokens, spentUSD, _tierPrice, _tier); } } diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 381584389..b4c1cb5d8 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -1,7 +1,8 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; -import "./CountTransferManagerStorage.sol"; +import "../../storage/modules/TransferManager/CountTransferManagerStorage.sol"; +import "../../interfaces/ISecurityToken.sol"; /** * @title Transfer Manager for limiting maximum number of token holders @@ -23,29 +24,49 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { * @param _to Address of the receiver * @param _amount Amount to send */ - function verifyTransfer( + function executeTransfer( address _from, address _to, uint256 _amount, - bytes calldata /* _data */, - bool /* _isTransfer */ + bytes calldata _data ) external returns(Result) + { + (Result success,) = verifyTransfer(_from, _to, _amount, _data); + return success; + } + + /** + * @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 _to, + uint256 _amount, + bytes memory /* _data */ + ) + public + view + returns(Result, bytes32) { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).holderCount()) { // Allow transfers to existing maxHolders if (ISecurityToken(securityToken).balanceOf(_to) != 0 || ISecurityToken(securityToken).balanceOf(_from) == _amount) { - return Result.NA; + return (Result.NA, bytes32(0)); } - return Result.INVALID; + return (Result.INVALID, bytes32(uint256(address(this)) << 96)); } - return Result.NA; + return (Result.NA, bytes32(0)); } - return Result.NA; + return (Result.NA, bytes32(0)); } + /** * @notice Used to initialize the variables of the contract * @param _maxHolderCount Maximum no. of holders this module allows the SecurityToken to have @@ -70,6 +91,13 @@ contract CountTransferManager is CountTransferManagerStorage, TransferManager { return bytes4(keccak256("configure(uint256)")); } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + /** * @notice Returns the permissions flag that are associated with CountTransferManager */ diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 981830437..f8731d46d 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -3,9 +3,9 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; import "../../libraries/Encoder.sol"; import "../../libraries/VersionUtils.sol"; -import "../../storage/GeneralTransferManagerStorage.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; +import "../../storage/modules/TransferManager/GeneralTransferManagerStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality @@ -140,6 +140,26 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage emit AllowAllBurnTransfers(_allowAllBurnTransfers); } + /** + * @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 + * b) Seller's sale lockup period is over + * c) Buyer's purchase lockup is over + * @param _from Address of the sender + * @param _to Address of the receiver + */ + function executeTransfer( + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external returns(Result) { + (Result success,) = verifyTransfer(_from, _to, _amount, _data); + return success; + } + /** * @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 @@ -154,9 +174,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage address _from, address _to, uint256, /*_amount*/ - bytes calldata, /* _data */ - bool /* _isTransfer */ - ) external returns(Result) { + bytes memory /* _data */ + ) + public + view + returns(Result, bytes32) + { + Result success; if (!paused) { uint64 fromTime; uint64 fromExpiry; @@ -164,37 +188,42 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint64 toTime; if (allowAllTransfers) { //All transfers allowed, regardless of whitelist - return Result.VALID; + return (Result.VALID, getAddressBytes32()); } if (allowAllBurnTransfers && (_to == address(0))) { - return Result.VALID; + return (Result.VALID, getAddressBytes32()); } (fromTime, fromExpiry, toTime, toExpiry) = _getValuesForTransfer(_from, _to); if (allowAllWhitelistTransfers) { //Anyone on the whitelist can transfer, regardless of time - return (_validExpiry(toExpiry) && _validExpiry(fromExpiry)) ? Result.VALID : Result.NA; + success = (_validExpiry(toExpiry) && _validExpiry(fromExpiry)) ? Result.VALID : Result.NA; + return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0)); } // Using the local variables to avoid the stack too deep error (fromTime, toTime) = _adjustTimes(fromTime, toTime); if (_from == issuanceAddress) { // if allowAllWhitelistIssuances is true, so time stamp ignored if (allowAllWhitelistIssuances) { - return _validExpiry(toExpiry) ? Result.VALID : Result.NA; + success = _validExpiry(toExpiry) ? Result.VALID : Result.NA; + return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0)); } else { - return (_validExpiry(toExpiry) && _validLockTime(toTime)) ? Result.VALID : Result.NA; + success = (_validExpiry(toExpiry) && _validLockTime(toTime)) ? Result.VALID : Result.NA; + return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0)); } } //Anyone on the whitelist can transfer provided the blocknumber is large enough /*solium-disable-next-line security/no-block-members*/ - return (_validExpiry(fromExpiry) && _validLockTime(fromTime) && _validExpiry(toExpiry) && + success = (_validExpiry(fromExpiry) && _validLockTime(fromTime) && _validExpiry(toExpiry) && _validLockTime(toTime)) ? Result.VALID : Result.NA; /*solium-disable-line security/no-block-members*/ + return (success, success == Result.VALID ? getAddressBytes32() : bytes32(0)); } - return Result.NA; + return (Result.NA, bytes32(0)); } + /** * @notice Add or remove KYC info of an investor. * @param _investor is the address to whitelist @@ -494,6 +523,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return (fromTimes, toTimes, expiryTimes); } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + /** * @notice Return the permissions flag that are associated with general trnasfer manager */ @@ -504,4 +540,8 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return allPermissions; } + function getAddressBytes32() public view returns(bytes32) { + return bytes32(uint256(address(this)) << 96); + } + } diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 167c80ac6..6501fc9a6 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -2,7 +2,7 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./ManualApprovalTransferManagerStorage.sol"; +import "../../storage/modules/TransferManager/ManualApprovalTransferManagerStorage.sol"; /** * @title Transfer Manager module for manually approving transactions between accounts @@ -54,34 +54,55 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, * @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( + function executeTransfer( address _from, address _to, uint256 _amount, - bytes calldata, /* _data */ - bool _isTransfer + bytes calldata _data ) external + onlySecurityToken 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) { + (Result success, bytes32 esc) = verifyTransfer(_from, _to, _amount, _data); + if (esc != bytes32(0)) { uint256 index = approvalIndex[_from][_to] - 1; ManualApproval storage approval = approvals[index]; + approval.allowance = approval.allowance.sub(_amount); + } + return (success); + } + + + /** + * @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 + */ + function verifyTransfer( + address _from, + address _to, + uint256 _amount, + bytes memory /* _data */ + ) + public + view + returns(Result, bytes32) + { + if (!paused && approvalIndex[_from][_to] != 0) { + uint256 index = approvalIndex[_from][_to] - 1; + ManualApproval memory approval = approvals[index]; if ((approval.expiryTime >= now) && (approval.allowance >= _amount)) { - if (_isTransfer) { - approval.allowance = approval.allowance.sub(_amount); - } - return Result.VALID; + return (Result.VALID, bytes32(uint256(address(this)) << 96)); } } - return Result.NA; + return (Result.NA, bytes32(0)); } + /** * @notice Adds a pair of addresses to manual approvals * @param _from is the address from which transfers are approved @@ -391,6 +412,13 @@ contract ManualApprovalTransferManager is ManualApprovalTransferManagerStorage, } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + /** * @notice Returns the permissions flag that are associated with ManualApproval transfer manager */ diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index dbcfc5906..8217a1b17 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -9,7 +9,7 @@ pragma solidity ^0.5.0; import "./TransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -import "./PercentageTransferManagerStorage.sol"; +import "../../storage/modules/TransferManager/PercentageTransferManagerStorage.sol"; /** * @title Transfer Manager module for limiting percentage of token supply a single address can hold @@ -25,7 +25,10 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer * @notice Constructor * @param _securityToken Address of the security token */ - constructor(address _securityToken, address _polyToken) public Module(_securityToken, _polyToken) { + constructor(address _securityToken, address _polyToken) + public + Module(_securityToken, _polyToken) + { } @@ -34,31 +37,50 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer * @param _to Address of the receiver * @param _amount The amount of tokens to transfer */ - function verifyTransfer( + function executeTransfer( address _from, address _to, uint256 _amount, - bytes calldata, /* _data */ - bool /* _isTransfer */ + bytes calldata _data ) external returns(Result) + { + (Result success,) = verifyTransfer(_from, _to, _amount, _data); + return success; + } + + /** + * @notice Used to verify the transfer transaction and prevent a given account to end up with more tokens than allowed + * @param _from Address of the sender + * @param _to Address of the receiver + * @param _amount The amount of tokens to transfer + */ + function verifyTransfer( + address _from, + address _to, + uint256 _amount, + bytes memory /*_data*/ + ) + public + view + returns(Result, bytes32) { if (!paused) { if (_from == address(0) && allowPrimaryIssuance) { - return Result.NA; + return (Result.NA, bytes32(0)); } // If an address is on the whitelist, it is allowed to hold more than maxHolderPercentage of the tokens. if (whitelist[_to]) { - return Result.NA; + return (Result.NA, bytes32(0)); } uint256 newBalance = IERC20(securityToken).balanceOf(_to).add(_amount); if (newBalance.mul(uint256(10) ** 18).div(IERC20(securityToken).totalSupply()) > maxHolderPercentage) { - return Result.INVALID; + return (Result.INVALID, bytes32(uint256(address(this)) << 96)); } - return Result.NA; + return (Result.NA, bytes32(0)); } - return Result.NA; + return (Result.NA, bytes32(0)); } /** @@ -120,6 +142,13 @@ contract PercentageTransferManager is PercentageTransferManagerStorage, Transfer emit SetAllowPrimaryIssuance(_allowPrimaryIssuance); } + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } + /** * @notice Return the permissions flag that are associated with Percentage transfer Manager */ diff --git a/contracts/modules/TransferManager/TransferManager.sol b/contracts/modules/TransferManager/TransferManager.sol index f8b75c250..bcf96e206 100644 --- a/contracts/modules/TransferManager/TransferManager.sol +++ b/contracts/modules/TransferManager/TransferManager.sol @@ -8,6 +8,15 @@ import "../../interfaces/ITransferManager.sol"; * @title Base abstract contract to be implemented by all Transfer Manager modules */ contract TransferManager is ITransferManager, Module, Pausable { + + bytes32 public constant LOCKED = "LOCKED"; + bytes32 public constant UNLOCKED = "UNLOCKED"; + + modifier onlySecurityToken() { + require(msg.sender == securityToken, "Sender is not owner"); + _; + } + function unpause() public onlyOwner { super._unpause(); } diff --git a/contracts/modules/TransferManager/VolumeRestrictionTM.sol b/contracts/modules/TransferManager/VolumeRestrictionTM.sol index 2a9bd7803..c57cc4929 100644 --- a/contracts/modules/TransferManager/VolumeRestrictionTM.sol +++ b/contracts/modules/TransferManager/VolumeRestrictionTM.sol @@ -107,26 +107,82 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, TransferManager { * 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 memory /*_data*/, bool _isTransfer) public returns (Result) { + function executeTransfer(address _from, address /*_to */, uint256 _amount, bytes calldata /*_data*/) external onlySecurityToken returns (Result success) { + uint256 fromTimestamp; + uint256 sumOfLastPeriod; + uint256 daysCovered; + uint256 dailyTime; + uint256 endTime; + bool isGlobal; + (success, fromTimestamp, sumOfLastPeriod, daysCovered, dailyTime, endTime, isGlobal) = _verifyTransfer(_from, _amount); + if (fromTimestamp != 0 || dailyTime != 0) { + _updateStorage( + _from, + _amount, + fromTimestamp, + sumOfLastPeriod, + daysCovered, + dailyTime, + endTime, + isGlobal + ); + } + return success; + } + + /** + * @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 + */ + function verifyTransfer( + address _from, + address /*_to*/ , + uint256 _amount, + bytes memory /*_data*/ + ) + public + view + returns (Result, bytes32) + { + + (Result success,,,,,,) = _verifyTransfer(_from, _amount); + if (success == Result.INVALID) + return (success, bytes32(uint256(address(this)) << 96)); + return (Result.NA, bytes32(0)); + } + + /** + * @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 + */ + function _verifyTransfer( + address _from, + uint256 _amount + ) + internal + view + returns (Result, uint256, uint256, uint256, uint256, uint256, bool) + { // 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) && exemptions.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 if ((individualRestrictions.individualRestriction[_from].endTime >= now && individualRestrictions.individualRestriction[_from].startTime <= now) || (individualRestrictions.individualDailyRestriction[_from].endTime >= now && individualRestrictions.individualDailyRestriction[_from].startTime <= now)) { - return _individualRestrictionCheck(_from, _amount, _isTransfer); + return _individualRestrictionCheck(_from, _amount); // If the `_from` doesn't fall under the individual category. It will processed with in the global category automatically } else if ((globalRestrictions.defaultRestriction.endTime >= now && globalRestrictions.defaultRestriction.startTime <= now) || (globalRestrictions.defaultDailyRestriction.endTime >= now && globalRestrictions.defaultDailyRestriction.startTime <= now)) { - return _defaultRestrictionCheck(_from, _amount, _isTransfer); + return _defaultRestrictionCheck(_from, _amount); } } - return Result.NA; + return (Result.NA, 0, 0, 0, 0, 0, false); } /** @@ -692,13 +748,18 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, TransferManager { * @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) internal view returns ( + Result success, + uint256 fromTimestamp, + uint256 sumOfLastPeriod, + uint256 daysCovered, + uint256 dailyTime, + uint256 endTime, + bool isGlobal + ) { // using the variable to avoid stack too deep error BucketDetails storage bucketDetails = bucketData.defaultUserToBucket[_from]; - uint256 daysCovered = globalRestrictions.defaultRestriction.rollingPeriodInDays; - uint256 fromTimestamp = 0; - uint256 sumOfLastPeriod = 0; - uint256 dailyTime = 0; + daysCovered = globalRestrictions.defaultRestriction.rollingPeriodInDays; bool allowedDefault = true; bool allowedDaily; if (globalRestrictions.defaultRestriction.endTime >= now && globalRestrictions.defaultRestriction.startTime <= now) { @@ -726,36 +787,30 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, TransferManager { } (allowedDaily, dailyTime) = _dailyTxCheck(_from, _amount, bucketDetails.dailyLastTradedDayTime, globalRestrictions.defaultDailyRestriction); - if (_isTransfer) { - _updateStorage( - _from, - _amount, - fromTimestamp, - sumOfLastPeriod, - daysCovered, - dailyTime, - globalRestrictions.defaultDailyRestriction.endTime, - true - ); - } - return ((allowedDaily && allowedDefault) == true ? Result.NA : Result.INVALID); + success = ((allowedDaily && allowedDefault) == true ? Result.NA : Result.INVALID); + endTime = globalRestrictions.defaultDailyRestriction.endTime; + isGlobal = true; } /** * @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) internal view returns ( + Result success, + uint256 fromTimestamp, + uint256 sumOfLastPeriod, + uint256 daysCovered, + uint256 dailyTime, + uint256 endTime, + bool allowedDaily + ) { // using the variable to avoid stack too deep error BucketDetails memory bucketDetails = bucketData.userToBucket[_from]; VolumeRestriction memory dailyRestriction = individualRestrictions.individualDailyRestriction[_from]; VolumeRestriction memory restriction = individualRestrictions.individualRestriction[_from]; - uint256 daysCovered = restriction.rollingPeriodInDays; - uint256 fromTimestamp = 0; - uint256 sumOfLastPeriod = 0; - uint256 dailyTime = 0; + daysCovered = restriction.rollingPeriodInDays; 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 @@ -780,20 +835,9 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, TransferManager { } } (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); + success = ((allowedDaily && allowedIndividual) ? Result.NA : Result.INVALID); + endTime = dailyRestriction.endTime; + allowedDaily = false; } function _dailyTxCheck( @@ -1081,7 +1125,12 @@ contract VolumeRestrictionTM is VolumeRestrictionTMStorage, TransferManager { return VolumeRestrictionLib.getRestrictionData(holderData, individualRestrictions); } - + /** + * @notice return the amount of tokens for a given user as per the partition + */ + function getTokensByPartition(address /*_owner*/, bytes32 /*_partition*/) external view returns(uint256){ + return 0; + } /** * @notice Returns the permissions flag that are associated with Percentage transfer Manager diff --git a/contracts/proxy/CappedSTOProxy.sol b/contracts/proxy/CappedSTOProxy.sol index 1dc3604af..264769608 100644 --- a/contracts/proxy/CappedSTOProxy.sol +++ b/contracts/proxy/CappedSTOProxy.sol @@ -3,9 +3,9 @@ pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; -import "../modules/STO/STOStorage.sol"; -import "../modules/ModuleStorage.sol"; -import "../modules/STO/CappedSTOStorage.sol"; +import "../storage/modules/STO/STOStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; +import "../storage/modules/STO/CappedSTOStorage.sol"; /** * @title CappedSTO module Proxy diff --git a/contracts/proxy/CountTransferManagerProxy.sol b/contracts/proxy/CountTransferManagerProxy.sol index f91c32646..5ec6727e4 100644 --- a/contracts/proxy/CountTransferManagerProxy.sol +++ b/contracts/proxy/CountTransferManagerProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../modules/TransferManager/CountTransferManagerStorage.sol"; +import "../storage/modules/TransferManager/CountTransferManagerStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title CountTransferManager module Proxy diff --git a/contracts/proxy/DummySTOProxy.sol b/contracts/proxy/DummySTOProxy.sol index 71873c4d6..3a9924b38 100644 --- a/contracts/proxy/DummySTOProxy.sol +++ b/contracts/proxy/DummySTOProxy.sol @@ -3,9 +3,9 @@ pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; -import "../modules/STO/STOStorage.sol"; -import "../modules/ModuleStorage.sol"; -import "../modules/STO/DummySTOStorage.sol"; +import "../storage/modules/STO/STOStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; +import "../storage/modules/STO/DummySTOStorage.sol"; /** * @title DummySTO module Proxy diff --git a/contracts/proxy/ERC20DividendCheckpointProxy.sol b/contracts/proxy/ERC20DividendCheckpointProxy.sol index 5dc0c8e63..be16be477 100644 --- a/contracts/proxy/ERC20DividendCheckpointProxy.sol +++ b/contracts/proxy/ERC20DividendCheckpointProxy.sol @@ -1,10 +1,10 @@ pragma solidity ^0.5.0; -import "../modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; -import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "../storage/modules/Checkpoint/ERC20DividendCheckpointStorage.sol"; +import "../storage/modules/Checkpoint/DividendCheckpointStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality diff --git a/contracts/proxy/EtherDividendCheckpointProxy.sol b/contracts/proxy/EtherDividendCheckpointProxy.sol index 381d71d27..cfbab6961 100644 --- a/contracts/proxy/EtherDividendCheckpointProxy.sol +++ b/contracts/proxy/EtherDividendCheckpointProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../modules/Checkpoint/DividendCheckpointStorage.sol"; +import "../storage/modules/Checkpoint/DividendCheckpointStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality diff --git a/contracts/proxy/GeneralPermissionManagerProxy.sol b/contracts/proxy/GeneralPermissionManagerProxy.sol index 6273cf874..51a39fbbc 100644 --- a/contracts/proxy/GeneralPermissionManagerProxy.sol +++ b/contracts/proxy/GeneralPermissionManagerProxy.sol @@ -3,9 +3,8 @@ pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; -import "../modules/STO/STOStorage.sol"; -import "../modules/ModuleStorage.sol"; -import "../modules/PermissionManager/GeneralPermissionManagerStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; +import "../storage/modules/PermissionManager/GeneralPermissionManagerStorage.sol"; /** * @title GeneralPermissionManager module Proxy diff --git a/contracts/proxy/GeneralTransferManagerProxy.sol b/contracts/proxy/GeneralTransferManagerProxy.sol index 0a4adbc08..a53fdcb84 100644 --- a/contracts/proxy/GeneralTransferManagerProxy.sol +++ b/contracts/proxy/GeneralTransferManagerProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../storage/GeneralTransferManagerStorage.sol"; +import "../storage/modules/TransferManager/GeneralTransferManagerStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality diff --git a/contracts/proxy/ManualApprovalTransferManagerProxy.sol b/contracts/proxy/ManualApprovalTransferManagerProxy.sol index e3b4f6bc0..a98eed41f 100644 --- a/contracts/proxy/ManualApprovalTransferManagerProxy.sol +++ b/contracts/proxy/ManualApprovalTransferManagerProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../modules/TransferManager/ManualApprovalTransferManagerStorage.sol"; +import "../storage/modules/TransferManager/ManualApprovalTransferManagerStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** @title ManualApprovalTransferManager module Proxy diff --git a/contracts/proxy/PercentageTransferManagerProxy.sol b/contracts/proxy/PercentageTransferManagerProxy.sol index 6c85d0f5f..bc5af795f 100644 --- a/contracts/proxy/PercentageTransferManagerProxy.sol +++ b/contracts/proxy/PercentageTransferManagerProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../modules/TransferManager/PercentageTransferManagerStorage.sol"; +import "../storage/modules/TransferManager/PercentageTransferManagerStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title PercentageTransferManager module Proxy diff --git a/contracts/proxy/PreSaleSTOProxy.sol b/contracts/proxy/PreSaleSTOProxy.sol index 2753ec3b9..e3fe6f573 100644 --- a/contracts/proxy/PreSaleSTOProxy.sol +++ b/contracts/proxy/PreSaleSTOProxy.sol @@ -3,9 +3,9 @@ pragma solidity ^0.5.0; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; -import "../modules/STO/STOStorage.sol"; -import "../modules/ModuleStorage.sol"; -import "../modules/STO/PreSaleSTOStorage.sol"; +import "../storage/modules/STO/STOStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; +import "../storage/modules/STO/PreSaleSTOStorage.sol"; /** * @title PreSaleSTO module Proxy diff --git a/contracts/proxy/USDTieredSTOProxy.sol b/contracts/proxy/USDTieredSTOProxy.sol index 1f5a1087a..109b1ad2e 100644 --- a/contracts/proxy/USDTieredSTOProxy.sol +++ b/contracts/proxy/USDTieredSTOProxy.sol @@ -1,11 +1,11 @@ pragma solidity ^0.5.0; -import "../storage/USDTieredSTOStorage.sol"; +import "../storage/modules/STO/USDTieredSTOStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; -import "../modules/STO/STOStorage.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/STO/STOStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title USDTiered STO module Proxy diff --git a/contracts/proxy/VestingEscrowWalletProxy.sol b/contracts/proxy/VestingEscrowWalletProxy.sol index a69463084..705adaf4a 100644 --- a/contracts/proxy/VestingEscrowWalletProxy.sol +++ b/contracts/proxy/VestingEscrowWalletProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../storage/VestingEscrowWalletStorage.sol"; +import "../storage/modules/Wallet/VestingEscrowWalletStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title Escrow wallet module for vesting functionality */ diff --git a/contracts/proxy/VolumeRestrictionTMProxy.sol b/contracts/proxy/VolumeRestrictionTMProxy.sol index ce1356904..4fb255dba 100644 --- a/contracts/proxy/VolumeRestrictionTMProxy.sol +++ b/contracts/proxy/VolumeRestrictionTMProxy.sol @@ -1,9 +1,9 @@ pragma solidity ^0.5.0; -import "../storage/VolumeRestrictionTMStorage.sol"; +import "../storage/modules/TransferManager/VolumeRestrictionTMStorage.sol"; import "./OwnedProxy.sol"; import "../Pausable.sol"; -import "../modules/ModuleStorage.sol"; +import "../storage/modules/ModuleStorage.sol"; /** * @title Transfer Manager module for core transfer validation functionality diff --git a/contracts/modules/Checkpoint/DividendCheckpointStorage.sol b/contracts/storage/modules/Checkpoint/DividendCheckpointStorage.sol similarity index 100% rename from contracts/modules/Checkpoint/DividendCheckpointStorage.sol rename to contracts/storage/modules/Checkpoint/DividendCheckpointStorage.sol diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol b/contracts/storage/modules/Checkpoint/ERC20DividendCheckpointStorage.sol similarity index 100% rename from contracts/modules/Checkpoint/ERC20DividendCheckpointStorage.sol rename to contracts/storage/modules/Checkpoint/ERC20DividendCheckpointStorage.sol diff --git a/contracts/modules/ModuleStorage.sol b/contracts/storage/modules/ModuleStorage.sol similarity index 100% rename from contracts/modules/ModuleStorage.sol rename to contracts/storage/modules/ModuleStorage.sol diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol b/contracts/storage/modules/PermissionManager/GeneralPermissionManagerStorage.sol similarity index 100% rename from contracts/modules/PermissionManager/GeneralPermissionManagerStorage.sol rename to contracts/storage/modules/PermissionManager/GeneralPermissionManagerStorage.sol diff --git a/contracts/modules/STO/CappedSTOStorage.sol b/contracts/storage/modules/STO/CappedSTOStorage.sol similarity index 100% rename from contracts/modules/STO/CappedSTOStorage.sol rename to contracts/storage/modules/STO/CappedSTOStorage.sol diff --git a/contracts/modules/STO/DummySTOStorage.sol b/contracts/storage/modules/STO/DummySTOStorage.sol similarity index 100% rename from contracts/modules/STO/DummySTOStorage.sol rename to contracts/storage/modules/STO/DummySTOStorage.sol diff --git a/contracts/modules/STO/ISTOStorage.sol b/contracts/storage/modules/STO/ISTOStorage.sol similarity index 100% rename from contracts/modules/STO/ISTOStorage.sol rename to contracts/storage/modules/STO/ISTOStorage.sol diff --git a/contracts/modules/STO/PreSaleSTOStorage.sol b/contracts/storage/modules/STO/PreSaleSTOStorage.sol similarity index 100% rename from contracts/modules/STO/PreSaleSTOStorage.sol rename to contracts/storage/modules/STO/PreSaleSTOStorage.sol diff --git a/contracts/modules/STO/STOStorage.sol b/contracts/storage/modules/STO/STOStorage.sol similarity index 100% rename from contracts/modules/STO/STOStorage.sol rename to contracts/storage/modules/STO/STOStorage.sol diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/modules/STO/USDTieredSTOStorage.sol similarity index 100% rename from contracts/storage/USDTieredSTOStorage.sol rename to contracts/storage/modules/STO/USDTieredSTOStorage.sol diff --git a/contracts/modules/TransferManager/CountTransferManagerStorage.sol b/contracts/storage/modules/TransferManager/CountTransferManagerStorage.sol similarity index 100% rename from contracts/modules/TransferManager/CountTransferManagerStorage.sol rename to contracts/storage/modules/TransferManager/CountTransferManagerStorage.sol diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/modules/TransferManager/GeneralTransferManagerStorage.sol similarity index 100% rename from contracts/storage/GeneralTransferManagerStorage.sol rename to contracts/storage/modules/TransferManager/GeneralTransferManagerStorage.sol diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol b/contracts/storage/modules/TransferManager/ManualApprovalTransferManagerStorage.sol similarity index 100% rename from contracts/modules/TransferManager/ManualApprovalTransferManagerStorage.sol rename to contracts/storage/modules/TransferManager/ManualApprovalTransferManagerStorage.sol diff --git a/contracts/modules/TransferManager/PercentageTransferManagerStorage.sol b/contracts/storage/modules/TransferManager/PercentageTransferManagerStorage.sol similarity index 100% rename from contracts/modules/TransferManager/PercentageTransferManagerStorage.sol rename to contracts/storage/modules/TransferManager/PercentageTransferManagerStorage.sol diff --git a/contracts/storage/VolumeRestrictionTMStorage.sol b/contracts/storage/modules/TransferManager/VolumeRestrictionTMStorage.sol similarity index 100% rename from contracts/storage/VolumeRestrictionTMStorage.sol rename to contracts/storage/modules/TransferManager/VolumeRestrictionTMStorage.sol diff --git a/contracts/storage/VestingEscrowWalletStorage.sol b/contracts/storage/modules/Wallet/VestingEscrowWalletStorage.sol similarity index 100% rename from contracts/storage/VestingEscrowWalletStorage.sol rename to contracts/storage/modules/Wallet/VestingEscrowWalletStorage.sol diff --git a/contracts/tokens/OZStorage.sol b/contracts/tokens/OZStorage.sol new file mode 100644 index 000000000..536b733c7 --- /dev/null +++ b/contracts/tokens/OZStorage.sol @@ -0,0 +1,28 @@ +pragma solidity ^0.5.0; + +contract OZStorage { + + mapping (address => uint256) private _balances; + + mapping (address => mapping (address => uint256)) private _allowed; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + uint8 private _decimals; + + address private _owner; + + /// @dev counter to allow mutex lock with only one SSTORE operation + uint256 private _guardCounter; + + function totalSupply() internal view returns (uint256) { + return _totalSupply; + } + + function balanceOf(address _investor) internal view returns(uint256) { + return _balances[_investor]; + } + +} \ No newline at end of file diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index ba97256a2..fc1029f37 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -9,11 +9,13 @@ import "../datastore/DataStoreFactory.sol"; */ contract STFactory is ISTFactory { address public transferManagerFactory; + address public stDelegate; DataStoreFactory public dataStoreFactory; - constructor(address _transferManagerFactory, address _dataStoreFactory) public { + constructor(address _transferManagerFactory, address _dataStoreFactory, address _stDelegate) public { transferManagerFactory = _transferManagerFactory; dataStoreFactory = DataStoreFactory(_dataStoreFactory); + stDelegate = _stDelegate; } /** @@ -38,7 +40,8 @@ contract STFactory is ISTFactory { _decimals, _divisible ? 1 : uint256(10) ** _decimals, _tokenDetails, - _polymathRegistry + _polymathRegistry, + stDelegate ); //NB When dataStore is generated, the security token address is automatically set via the constructor in DataStoreProxy. newSecurityToken.changeDataStore(dataStoreFactory.generateDataStore(address(newSecurityToken))); diff --git a/contracts/tokens/STGetter.sol b/contracts/tokens/STGetter.sol new file mode 100644 index 000000000..e1712396a --- /dev/null +++ b/contracts/tokens/STGetter.sol @@ -0,0 +1,210 @@ +pragma solidity ^0.5.0; + +import "./OZStorage.sol"; +import "./SecurityTokenStorage.sol"; +import "../libraries/TokenLib.sol"; +import "../interfaces/IDataStore.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../modules/PermissionManager/IPermissionManager.sol"; + +contract STGetter is OZStorage, SecurityTokenStorage { + + using SafeMath for uint256; + + /** + * @notice Used to return the details of a document with a known name (`bytes32`). + * @param _name Name of the document + * @return string The URI associated with the document. + * @return bytes32 The hash (of the contents) of the document. + * @return uint256 the timestamp at which the document was last modified. + */ + function getDocument(bytes32 _name) external view returns (string memory, bytes32, uint256) { + return ( + _documents[_name].uri, + _documents[_name].docHash, + _documents[_name].lastModified + ); + } + + /** + * @notice Used to retrieve a full list of documents attached to the smart contract. + * @return bytes32 List of all documents names present in the contract. + */ + function getAllDocuments() external view returns (bytes32[] memory) { + return _docNames; + } + + /** + * @notice Gets list of times that checkpoints were created + * @return List of checkpoint times + */ + function getCheckpointTimes() external view returns(uint256[] memory) { + return checkpointTimes; + } + + /** + * @notice Returns the count of address that were added as (potential) investors + * @return Investor count + */ + function getInvestorCount() external view returns(uint256) { + IDataStore dataStoreInstance = IDataStore(dataStore); + return dataStoreInstance.getAddressArrayLength(INVESTORSKEY); + } + + /** + * @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() public view returns(address[] memory investors) { + IDataStore dataStoreInstance = IDataStore(dataStore); + investors = dataStoreInstance.getAddressArray(INVESTORSKEY); + } + + /** + * @notice returns an array of investors with non zero balance at a given checkpoint + * @param _checkpointId Checkpoint id at which investor list is to be populated + * @return list of investors + */ + function getInvestorsAt(uint256 _checkpointId) external view returns(address[] memory) { + uint256 count; + uint256 i; + IDataStore dataStoreInstance = IDataStore(dataStore); + address[] memory investors = dataStoreInstance.getAddressArray(INVESTORSKEY); + for (i = 0; i < investors.length; i++) { + if (balanceOfAt(investors[i], _checkpointId) > 0) { + count++; + } + } + address[] memory holders = new address[](count); + count = 0; + for (i = 0; i < investors.length; i++) { + if (balanceOfAt(investors[i], _checkpointId) > 0) { + holders[count] = investors[i]; + count++; + } + } + return holders; + } + + /** + * @notice Returns the data associated to a module + * @param _module address of the module + * @return bytes32 name + * @return address module address + * @return address module factory address + * @return bool module archived + * @return uint8 array of module types + * @return bytes32 module label + */ + function getModule(address _module) external view returns(bytes32, address, address, bool, uint8[] memory, bytes32) { + return ( + modulesToData[_module].name, + modulesToData[_module].module, + modulesToData[_module].moduleFactory, + modulesToData[_module].isArchived, + modulesToData[_module].moduleTypes, + modulesToData[_module].label + ); + } + + /** + * @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 + */ + function getModulesByName(bytes32 _name) external view returns(address[] memory) { + return names[_name]; + } + + /** + * @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 + */ + function getModulesByType(uint8 _type) external view returns(address[] memory) { + return modules[_type]; + } + + /** + * @notice Queries balances as of a defined checkpoint + * @param _investor Investor to query balance for + * @param _checkpointId Checkpoint ID to query as of + */ + function balanceOfAt(address _investor, uint256 _checkpointId) public view returns(uint256) { + require(_checkpointId <= currentCheckpointId); + return TokenLib.getValueAt(checkpointBalances[_investor], _checkpointId, balanceOf(_investor)); + } + + /** + * @notice Queries totalSupply as of a defined checkpoint + * @param _checkpointId Checkpoint ID to query + * @return uint256 + */ + function totalSupplyAt(uint256 _checkpointId) external view returns(uint256) { + require(_checkpointId <= currentCheckpointId); + return checkpointTotalSupply[_checkpointId]; + } + + /** + * @notice generates subset of investors + * NB - can be used in batches if investor list is large. start and end both are included in array. + * @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[] memory) { + IDataStore dataStoreInstance = IDataStore(dataStore); + return dataStoreInstance.getAddressArrayElements(INVESTORSKEY, _start, _end); + } + + /** + * @notice Validate permissions with PermissionManager if it exists, If no Permission return false + * @dev Note that IModule withPerm will allow ST owner all permissions anyway + * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) + * @param _delegate address of delegate + * @param _module address of PermissionManager module + * @param _perm the permissions + * @return success + */ + function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) { + for (uint256 i = 0; i < modules[PERMISSION_KEY].length; i++) { + if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived) { + if (IPermissionManager(modules[PERMISSION_KEY][i]).checkPermission(_delegate, _module, _perm)) { + return true; + } + } + } + return false; + } + + /** + * @notice Get the balance according to the provided partitions + * @param _owner Whom balance need to queried + * @param _partition Partition which differentiate the tokens. + * @return Amount of tokens as per the given partitions + */ + function balanceOfByPartition(address _owner, bytes32 _partition) external view returns(uint256) { + address[] memory tms = modules[TRANSFER_KEY]; + uint256 _amount = 0; + for (uint256 i = 0; i < tms.length; i++) { + _amount += ITransferManager(tms[i]).getTokensByPartition(_owner, _partition); + } + if (_amount == 0 && _partition == "UNLOCKED") { + return balanceOf(_owner); + } + return _amount; + } + + /** + * @notice Returns the version of the SecurityToken + */ + function getVersion() external view returns(uint8[] memory) { + uint8[] memory _version = new uint8[](3); + _version[0] = securityTokenVersion.major; + _version[1] = securityTokenVersion.minor; + _version[2] = securityTokenVersion.patch; + return _version; + } + +} \ No newline at end of file diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 9f7b7fe59..d76d8ad32 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -1,96 +1,46 @@ pragma solidity ^0.5.0; -import "openzeppelin-solidity/contracts/math/Math.sol"; -import "../interfaces/IPoly.sol"; +import "../proxy/Proxy.sol"; +import "../PolymathRegistry.sol"; +import "../libraries/KindMath.sol"; import "../interfaces/IModule.sol"; +import "./SecurityTokenStorage.sol"; +import "../libraries/TokenLib.sol"; import "../interfaces/IModuleFactory.sol"; +import "../interfaces/token/IERC1594.sol"; +import "../interfaces/token/IERC1643.sol"; +import "../interfaces/token/IERC1644.sol"; import "../interfaces/IModuleRegistry.sol"; import "../interfaces/IFeatureRegistry.sol"; import "../interfaces/ITransferManager.sol"; -import "../modules/PermissionManager/IPermissionManager.sol"; -import "../RegistryUpdater.sol"; -import "../libraries/Util.sol"; +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; +import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol"; -import "../libraries/TokenLib.sol"; -import "../interfaces/IDataStore.sol"; /** -* @title Security Token contract -* @notice SecurityToken is an ERC20 token with added capabilities: -* @notice - Implements the ST-20 Interface -* @notice - Transfers are restricted -* @notice - Modules can be attached to it to control its behaviour -* @notice - ST should not be deployed directly, but rather the SecurityTokenRegistry should be used -* @notice - ST does not inherit from ISecurityToken due to: -* @notice - https://github.com/ethereum/solidity/issues/4847 -*/ -contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater { + * @title Security Token contract + * @notice SecurityToken is an ERC1400 token with added capabilities: + * @notice - Implements the ERC1400 Interface + * @notice - Transfers are restricted + * @notice - Modules can be attached to it to control its behaviour + * @notice - ST should not be deployed directly, but rather the SecurityTokenRegistry should be used + * @notice - ST does not inherit from ISecurityToken due to: + * @notice - https://github.com/ethereum/solidity/issues/4847 + */ +contract SecurityToken is ERC20, ERC20Detailed, Ownable, ReentrancyGuard, SecurityTokenStorage, IERC1594, IERC1643, IERC1644, Proxy { + using SafeMath for uint256; - bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) - - // Used to hold the semantic version data - struct SemanticVersion { - uint8 major; - uint8 minor; - uint8 patch; - } - - SemanticVersion securityTokenVersion; - - // off-chain data - string public tokenDetails; - - uint8 constant PERMISSION_KEY = 1; - uint8 constant TRANSFER_KEY = 2; - uint8 constant MINT_KEY = 3; - uint8 constant CHECKPOINT_KEY = 4; - uint8 constant BURN_KEY = 5; - uint8 constant DATA_KEY = 6; - - uint256 public granularity; - - // Value of current checkpoint - uint256 public currentCheckpointId; - - // Used to temporarily halt all transactions - bool public transfersFrozen; - - // Used to permanently halt all minting - bool public mintingFrozen; - - // Used to permanently halt controller actions - bool public controllerDisabled; - - // Address whitelisted by issuer as controller - address public controller; - - // Address of the data store used to store shared data - address public dataStore; - - // Number of investors with non-zero balance - uint256 public holderCount; - - // Records added modules - module list should be order agnostic! - mapping(uint8 => address[]) modules; - - // Records information about the module - mapping(address => TokenLib.ModuleData) modulesToData; - - // Records added module names - module list should be order agnostic! - mapping(bytes32 => address[]) names; - - // Map each investor to a series of checkpoints - mapping(address => TokenLib.Checkpoint[]) checkpointBalances; - - // Mapping of checkpoints that relate to total supply - mapping (uint256 => uint256) checkpointTotalSupply; - - // Times at which each checkpoint was created - uint256[] checkpointTimes; - + // Emit when transfers are frozen or unfrozen + event FreezeTransfers(bool _status); + // Emit when is permanently frozen by the issuer + event FreezeIssuance(); + // Emit when the token details get updated + event UpdateTokenDetails(string _oldDetails, string _newDetails); + // Emit when the granularity get changed + event GranularityChanged(uint256 _oldGranularity, uint256 _newGranularity); // Emit at the time when module get added event ModuleAdded( uint8[] _types, @@ -101,11 +51,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _budget, bytes32 _label ); - - // Emit when the token details get updated - event UpdateTokenDetails(string _oldDetails, string _newDetails); - // Emit when the granularity get changed - event GranularityChanged(uint256 _oldGranularity, uint256 _newGranularity); // Emit when Module get archived from the securityToken event ModuleArchived(uint8[] _types, address _module); // Emit when Module get unarchived from the securityToken @@ -114,29 +59,12 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater event ModuleRemoved(uint8[] _types, address _module); // Emit when the budget allocated to a module is changed event ModuleBudgetChanged(uint8[] _moduleTypes, address _module, uint256 _oldBudget, uint256 _budget); - // Emit when transfers are frozen or unfrozen - event FreezeTransfers(bool _status); // Emit when new checkpoint created event CheckpointCreated(uint256 indexed _checkpointId); - // Emit when is permanently frozen by the issuer - event FreezeMinting(); - // 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 DisableController(); - + function _isModule(address _module, uint8 _type) internal view returns(bool) { if (modulesToData[_module].module != _module || modulesToData[_module].isArchived) return false; @@ -164,13 +92,19 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater } } + modifier isIssuanceAllowed() { + require(issuance, "Issuance frozen"); + _; + } + modifier checkGranularity(uint256 _value) { require(_value % granularity == 0, "Invalid granularity"); _; } - - modifier isMintingAllowed() { - require(!mintingFrozen, "Minting frozen"); + + // Modifier to check whether the msg.sender is authorised or not + modifier onlyController() { + require(msg.sender == controller, "Not Authorised"); _; } @@ -178,24 +112,16 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater require(IFeatureRegistry(featureRegistry).getFeatureStatus(_nameKey)); _; } - - /** - * @notice Revert if called by an account which is not a controller - */ - modifier onlyController() { - require(msg.sender == controller, "Not controller"); - require(!controllerDisabled, "Controller disabled"); - _; - } - + /** - * @notice Constructor + * @notice constructor * @param _name Name of the SecurityToken * @param _symbol Symbol of the Token * @param _decimals Decimals for the securityToken * @param _granularity granular level of the token * @param _tokenDetails Details of the token that are stored off-chain * @param _polymathRegistry Contract address of the polymath registry + * @param _delegate Contract address of the delegate */ constructor( string memory _name, @@ -203,13 +129,18 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint8 _decimals, uint256 _granularity, string memory _tokenDetails, - address _polymathRegistry - ) + address _polymathRegistry, + address _delegate + ) public - ERC20Detailed(_name, _symbol, _decimals) RegistryUpdater(_polymathRegistry) + ERC20Detailed(_name, _symbol, _decimals) { + require(_polymathRegistry != address(0), "Invalid address"); + require(_delegate != address(0), "Invalid address"); + polymathRegistry = _polymathRegistry; //When it is created, the owner is the STR updateFromRegistry(); + delegate = _delegate; tokenDetails = _tokenDetails; granularity = _granularity; securityTokenVersion = SemanticVersion(2, 0, 0); @@ -231,9 +162,10 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 _maxCost, uint256 _budget, bytes32 _label - ) - public - onlyOwner nonReentrant + ) + public + onlyOwner + nonReentrant { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); @@ -256,7 +188,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater moduleIndexes[i] = modules[moduleTypes[i]].length; modules[moduleTypes[i]].push(module); } - modulesToData[module] = TokenLib.ModuleData( + modulesToData[module] = ModuleData( moduleName, module, _moduleFactory, @@ -303,38 +235,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater TokenLib.removeModule(_module, modules, modulesToData, names); } - /** - * @notice Returns the data associated to a module - * @param _module address of the module - * @return bytes32 name - * @return address module address - * @return address module factory address - * @return bool module archived - * @return uint8 array of module types - * @return bytes32 module label - */ - function getModule(address _module) external view returns(bytes32, address, address, bool, uint8[] memory, bytes32) { - return (modulesToData[_module].name, modulesToData[_module].module, modulesToData[_module].moduleFactory, modulesToData[_module].isArchived, modulesToData[_module].moduleTypes, modulesToData[_module].label); - } - - /** - * @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 - */ - function getModulesByName(bytes32 _name) external view returns(address[] memory) { - return names[_name]; - } - - /** - * @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 - */ - function getModulesByType(uint8 _type) external view returns(address[] memory) { - return modules[_type]; - } - /** * @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. @@ -395,63 +295,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater holderCount = TokenLib.adjustInvestorCount(holderCount, _from, _to, _value, balanceOf(_to), balanceOf(_from), dataStore); } - /** - * @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() public view returns(address[] memory investors) { - IDataStore dataStoreInstance = IDataStore(dataStore); - investors = dataStoreInstance.getAddressArray(INVESTORSKEY); - } - - /** - * @notice returns an array of investors with non zero balance at a given checkpoint - * @param _checkpointId Checkpoint id at which investor list is to be populated - * @return list of investors - */ - function getInvestorsAt(uint256 _checkpointId) external view returns(address[] memory) { - uint256 count; - uint256 i; - IDataStore dataStoreInstance = IDataStore(dataStore); - address[] memory investors = dataStoreInstance.getAddressArray(INVESTORSKEY); - for (i = 0; i < investors.length; i++) { - if (balanceOfAt(investors[i], _checkpointId) > 0) { - count++; - } - } - address[] memory holders = new address[](count); - count = 0; - for (i = 0; i < investors.length; i++) { - if (balanceOfAt(investors[i], _checkpointId) > 0) { - holders[count] = investors[i]; - count++; - } - } - return holders; - } - - /** - * @notice generates subset of investors - * NB - can be used in batches if investor list is large. start and end both are included in array. - * @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[] memory) { - IDataStore dataStoreInstance = IDataStore(dataStore); - return dataStoreInstance.getAddressArrayElements(INVESTORSKEY, _start, _end); - } - - /** - * @notice Returns the count of address that were added as (potential) investors - * @return Investor count - */ - function getInvestorCount() external view returns(uint256) { - IDataStore dataStoreInstance = IDataStore(dataStore); - return dataStoreInstance.getAddressArrayLength(INVESTORSKEY); - } - /** * @notice freezes transfers */ @@ -472,7 +315,6 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater emit FreezeTransfers(false); } - /** /** * @notice Internal - adjusts token holder balance at checkpoint before a token transfer * @param _investor address of the token holder affected @@ -488,20 +330,24 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return bool success */ function transfer(address _to, uint256 _value) public returns(bool success) { - return transferWithData(_to, _value, ""); + transferWithData(_to, _value, ""); + return true; } - + /** - * @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 + * @notice Transfer restrictions can take many forms and typically involve on-chain rules or whitelists. + * However for many types of approved transfers, maintaining an on-chain list of approved transfers can be + * cumbersome and expensive. An alternative is the co-signing approach, where in addition to the token holder + * approving a token transfer, and authorised entity provides signed data which further validates the transfer. + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. + * for the token contract to interpret or record. This could be signed data authorising the transfer + * (e.g. a dynamic whitelist) but is flexible enough to accomadate other use-cases. */ - function transferWithData(address _to, uint256 _value, bytes memory _data) public returns(bool success) { + function transferWithData(address _to, uint256 _value, bytes memory _data) public { require(_updateTransfer(msg.sender, _to, _value, _data), "Transfer invalid"); require(super.transfer(_to, _value)); - return true; } /** @@ -512,21 +358,26 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return bool success */ function transferFrom(address _from, address _to, uint256 _value) public returns(bool) { - return transferFromWithData(_from, _to, _value, ""); + transferFromWithData(_from, _to, _value, ""); + return true; } /** - * @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 + * @notice Transfer restrictions can take many forms and typically involve on-chain rules or whitelists. + * However for many types of approved transfers, maintaining an on-chain list of approved transfers can be + * cumbersome and expensive. An alternative is the co-signing approach, where in addition to the token holder + * approving a token transfer, and authorised entity provides signed data which further validates the transfer. + * @dev `msg.sender` MUST have a sufficient `allowance` set and this `allowance` must be debited by the `_value`. + * @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 + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. + * for the token contract to interpret or record. This could be signed data authorising the transfer + * (e.g. a dynamic whitelist) but is flexible enough to accomadate other use-cases. */ - function transferFromWithData(address _from, address _to, uint256 _value, bytes memory _data) public returns(bool) { + function transferFromWithData(address _from, address _to, uint256 _value, bytes memory _data) public { require(_updateTransfer(_from, _to, _value, _data), "Transfer invalid"); require(super.transferFrom(_from, _to, _value)); - return true; } /** @@ -546,7 +397,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater // - 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); + bool verified = _executeTransfer(_from, _to, _value, _data); _adjustBalanceCheckpoints(_from); _adjustBalanceCheckpoints(_to); return verified; @@ -555,28 +406,23 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /** * @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 - * 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). * @param _from sender of transfer * @param _to receiver of transfer * @param _value value of transfer * @param _data data to indicate validation - * @param _isTransfer whether transfer is being executed * @return bool */ - function _verifyTransfer( + function _executeTransfer( address _from, address _to, uint256 _value, - bytes memory _data, - bool _isTransfer - ) - internal - checkGranularity(_value) - returns(bool) - { + bytes memory _data + ) + internal + checkGranularity(_value) + returns(bool) + { if (!transfersFrozen) { bool isInvalid = false; bool isValid = false; @@ -587,7 +433,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater module = modules[TRANSFER_KEY][i]; if (!modulesToData[module].isArchived) { unarchived = true; - ITransferManager.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _data, _isTransfer); + ITransferManager.Result valid = ITransferManager(module).executeTransfer(_from, _to, _value, _data); if (valid == ITransferManager.Result.INVALID) { isInvalid = true; } else if (valid == ITransferManager.Result.VALID) { @@ -604,96 +450,74 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater } /** - * @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 - * @param _value value of transfer - * @param _data data to indicate validation - * @return bool + * @notice A security token issuer can specify that issuance has finished for the token + * (i.e. no new tokens can be minted or issued). + * @dev If a token returns FALSE for `isIssuable()` then it MUST always return FALSE in the future. + * If a token returns FALSE for `isIssuable()` then it MUST never allow additional tokens to be issued. + * @return bool `true` signifies the minting is allowed. While `false` denotes the end of minting */ - function verifyTransfer(address _from, address _to, uint256 _value, bytes memory _data) public returns(bool) { - return _verifyTransfer(_from, _to, _value, _data, false); + function isIssuable() external view returns (bool) { + return issuance; } /** - * @notice Permanently freeze minting of this security token. + * @notice Permanently freeze issuance of this security token. * @dev It MUST NOT be possible to increase `totalSuppy` after this function is called. */ - function freezeMinting() external isMintingAllowed isEnabled("freezeMintingAllowed") onlyOwner { - mintingFrozen = true; + function freezeIssuance() external isIssuanceAllowed isEnabled("freezeIssuanceAllowed") onlyOwner { + issuance = false; /*solium-disable-next-line security/no-block-members*/ - emit FreezeMinting(); + emit FreezeIssuance(); } /** - * @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 - * @return success + * @notice This function must be called to increase the total supply (Corresponds to mint function of ERC20). + * @dev It only be called by the token issuer or the operator defined by the issuer. ERC1594 doesn't have + * have the any logic related to operator but its superset ERC1400 have the operator logic and this function + * is allowed to call by the operator. + * @param _tokenHolder The account that will receive the created tokens (account should be whitelisted or KYCed). + * @param _value The amount of tokens need to be issued + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. */ - function mint(address _investor, uint256 _value) public returns(bool success) { - return mintWithData(_investor, _value, ""); - } - - /** - * @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 - * @param _data data to indicate validation - * @return success - */ - function mintWithData( - address _investor, + function issue( + address _tokenHolder, uint256 _value, bytes memory _data - ) - public - onlyModuleOrOwner(MINT_KEY) - isMintingAllowed - returns(bool success) + ) + public + isIssuanceAllowed + onlyModuleOrOwner(MINT_KEY) { - require(_updateTransfer(address(0), _investor, _value, _data), "Transfer invalid"); - _mint(_investor, _value); - emit Minted(_investor, _value); - return true; + // Add a function to validate the `_data` parameter + require(_updateTransfer(address(0), _tokenHolder, _value, _data), "Transfer invalid"); + _mint(_tokenHolder, _value); + emit Issued(msg.sender, _tokenHolder, _value, _data); } /** - * @notice Mints new tokens and assigns them to the target _investor. + * @notice issue new tokens and assigns them to the target _tokenHolder. * @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 + * @param _tokenHolders 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 _tokenHolders[] list * @return success */ - function mintMulti(address[] calldata _investors, uint256[] calldata _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]); + function issueMulti(address[] calldata _tokenHolders, uint256[] calldata _values) external { + require(_tokenHolders.length == _values.length, "Incorrect inputs"); + for (uint256 i = 0; i < _tokenHolders.length; i++) { + issue(_tokenHolders[i], _values[i], ""); } - return true; } /** - * @notice Validate permissions with PermissionManager if it exists, If no Permission return false - * @dev Note that IModule withPerm will allow ST owner all permissions anyway - * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) - * @param _delegate address of delegate - * @param _module address of PermissionManager module - * @param _perm the permissions - * @return success + * @notice This function redeem an amount of the token of a msg.sender. For doing so msg.sender may incentivize + * using different ways that could be implemented with in the `redeem` function definition. But those implementations + * are out of the scope of the ERC1594. + * @param _value The amount of tokens need to be redeemed + * @param _data The `bytes _data` it can be used in the token contract to authenticate the redemption. */ - function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) { - for (uint256 i = 0; i < modules[PERMISSION_KEY].length; i++) { - if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived) { - if (IPermissionManager(modules[PERMISSION_KEY][i]).checkPermission(_delegate, _module, _perm)) { - return true; - } - } - } - return false; + function redeem(uint256 _value, bytes calldata _data) external onlyModule(BURN_KEY) { + // Add a function to validate the `_data` parameter + require(_checkAndBurn(msg.sender, _value, _data), "Invalid redeem"); } /** @@ -708,34 +532,24 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater function _checkAndBurn(address _from, uint256 _value, bytes memory _data) internal returns(bool) { bool verified = _updateTransfer(_from, address(0), _value, _data); _burn(_from, _value); - emit Burnt(_from, _value); + emit Redeemed(address(0), msg.sender, _value, _data); return verified; } /** - * @notice Burn function used to burn the securityToken - * @param _value No. of tokens that get burned - * @param _data data to indicate validation + * @notice This function redeem an amount of the token of a msg.sender. For doing so msg.sender may incentivize + * using different ways that could be implemented with in the `redeem` function definition. But those implementations + * are out of the scope of the ERC1594. + * @dev It is analogy to `transferFrom` + * @param _tokenHolder The account whose tokens gets redeemed. + * @param _value The amount of tokens need to be redeemed + * @param _data The `bytes _data` it can be used in the token contract to authenticate the redemption. */ - function burnWithData(uint256 _value, bytes memory _data) public onlyModule(BURN_KEY) { - require(_checkAndBurn(msg.sender, _value, _data), "Burn invalid"); - } - - function _checkAndBurnFrom(address _from, uint256 _value, bytes memory _data) internal returns(bool) { - bool verified = _updateTransfer(_from, address(0), _value, _data); - _burnFrom(_from, _value); - emit Burnt(_from, _value); - return verified; - } - - /** - * @notice Burn function used to burn the securityToken on behalf of someone else - * @param _from Address for whom to burn tokens - * @param _value No. of tokens that get burned - * @param _data data to indicate validation - */ - function burnFromWithData(address _from, uint256 _value, bytes memory _data) public onlyModule(BURN_KEY) { - require(_checkAndBurnFrom(_from, _value, _data), "Burn invalid"); + function redeemFrom(address _tokenHolder, uint256 _value, bytes calldata _data) external onlyModule(BURN_KEY) { + // Add a function to validate the `_data` parameter + require(_updateTransfer(_tokenHolder, address(0), _value, _data), "Invalid redeem"); + _burnFrom(_tokenHolder, _value); + emit Redeemed(msg.sender, _tokenHolder, _value, _data); } /** @@ -754,89 +568,187 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater } /** - * @notice Gets list of times that checkpoints were created - * @return List of checkpoint times + * @notice Used by the issuer to set the controller addresses + * @param _controller address of the controller */ - function getCheckpointTimes() external view returns(uint256[] memory) { - return checkpointTimes; + function setController(address _controller) public onlyOwner { + require(_isControllable()); + // Below condition is to restrict the owner/issuer to become the controller(In an ideal world). + // But for non ideal case issuer could set another address which is not the owner of the token + // but issuer holds its private key. + require(_controller != msg.sender); + emit SetController(controller, _controller); + controller = _controller; } /** - * @notice Queries totalSupply as of a defined checkpoint - * @param _checkpointId Checkpoint ID to query - * @return uint256 + * @notice Used by the issuer to permanently disable controller functionality + * @dev enabled via feature switch "disableControllerAllowed" */ - function totalSupplyAt(uint256 _checkpointId) external view returns(uint256) { - require(_checkpointId <= currentCheckpointId); - return checkpointTotalSupply[_checkpointId]; + function disableController() external isEnabled("disableControllerAllowed") onlyOwner { + require(_isControllable()); + controllerDisabled = true; + delete controller; + emit DisableController(); } /** - * @notice Queries balances as of a defined checkpoint - * @param _investor Investor to query balance for - * @param _checkpointId Checkpoint ID to query as of + * @notice Transfers of securities may fail for a number of reasons. So this function will used to understand the + * cause of failure by getting the byte value. Which will be the ESC that follows the EIP 1066. ESC can be mapped + * with a reson string to understand the failure cause, table of Ethereum status code will always reside off-chain + * @param _to address The address which you want to transfer to + * @param _value uint256 the amount of tokens to be transferred + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. + * @return bool It signifies whether the transaction will be executed or not. + * @return byte Ethereum status code (ESC) + * @return bytes32 Application specific reason code */ - function balanceOfAt(address _investor, uint256 _checkpointId) public view returns(uint256) { - require(_checkpointId <= currentCheckpointId); - return TokenLib.getValueAt(checkpointBalances[_investor], _checkpointId, balanceOf(_investor)); + function canTransfer(address _to, uint256 _value, bytes calldata _data) external view returns (bool, byte, bytes32) { + return _canTransfer(msg.sender, _to, _value, _data); } /** - * @notice Used by the issuer to set the controller addresses - * @param _controller address of the controller + * @notice Transfers of securities may fail for a number of reasons. So this function will used to understand the + * cause of failure by getting the byte value. Which will be the ESC that follows the EIP 1066. ESC can be mapped + * with a reson string to understand the failure cause, table of Ethereum status code will always reside off-chain + * @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 + * @param _data The `bytes _data` allows arbitrary data to be submitted alongside the transfer. + * @return bool It signifies whether the transaction will be executed or not. + * @return byte Ethereum status code (ESC) + * @return bytes32 Application specific reason code */ - function setController(address _controller) public onlyOwner { - require(!controllerDisabled); - emit SetController(controller, _controller); - controller = _controller; + function canTransferFrom(address _from, address _to, uint256 _value, bytes calldata _data) external view returns (bool, byte, bytes32) { + (bool success, byte reasonCode, bytes32 appCode) = _canTransfer(_from, _to, _value, _data); + if (success && _value > allowance(_from, msg.sender)) { + return (false, 0x53, bytes32(0)); + } else + return (success, reasonCode, appCode); + } + + function _canTransfer(address _from, address _to, uint256 _value, bytes memory _data) internal view returns (bool, byte, bytes32) { + bytes32 appCode; + bool success; + if (_value % granularity != 0) { + return (false, 0x50, "Invalid granularity"); + } + (success, appCode) = TokenLib.verifyTransfer(modules[TRANSFER_KEY], modulesToData, _from, _to, _value, _data, transfersFrozen); + if (!success) + return (false, 0x50, appCode); + + else if (balanceOf(_from) < _value) + return (false, 0x52, bytes32(0)); + + else if (_to == address(0)) + return (false, 0x57, bytes32(0)); + + else if (!KindMath.checkAdd(balanceOf(_to), _value)) + return (false, 0x50, bytes32(0)); + return (true, 0x51, bytes32(0)); } /** - * @notice Used by the issuer to permanently disable controller functionality - * @dev enabled via feature switch "disableControllerAllowed" + * @notice Used to attach a new document to the contract, or update the URI or hash of an existing attached document + * @dev Can only be executed by the owner of the contract. + * @param _name Name of the document. It should be unique always + * @param _uri Off-chain uri of the document from where it is accessible to investors/advisors to read. + * @param _documentHash hash (of the contents) of the document. */ - function disableController() external isEnabled("disableControllerAllowed") onlyOwner { - require(!controllerDisabled); - controllerDisabled = true; - delete controller; - /*solium-disable-next-line security/no-block-members*/ - emit DisableController(); + function setDocument(bytes32 _name, string calldata _uri, bytes32 _documentHash) external onlyOwner { + require(_name != bytes32(0), "Zero value is not allowed"); + require(bytes(_uri).length > 0, "Should not be a empty uri"); + if (_documents[_name].lastModified == uint256(0)) { + _docNames.push(_name); + _docIndexes[_name] = _docNames.length; + } + _documents[_name] = Document(_documentHash, now, _uri); + emit DocumentUpdated(_name, _uri, _documentHash); } /** - * @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 + * @notice Used to remove an existing document from the contract by giving the name of the document. + * @dev Can only be executed by the owner of the contract. + * @param _name Name of the document. It should be unique always */ - function forceTransfer(address _from, address _to, uint256 _value, bytes memory _data, bytes memory _log) public onlyController { - bool verified = _updateTransfer(_from, _to, _value, _data); - _transfer(_from, _to, _value); - emit ForceTransfer(msg.sender, _from, _to, _value, verified, _log); + function removeDocument(bytes32 _name) external onlyOwner { + require(_documents[_name].lastModified != uint256(0), "Document should be existed"); + uint256 index = _docIndexes[_name] - 1; + if (index != _docNames.length - 1) { + _docNames[index] = _docNames[_docNames.length - 1]; + _docIndexes[_docNames[index]] = index + 1; + } + _docNames.length--; + emit DocumentRemoved(_name, _documents[_name].uri, _documents[_name].docHash); + delete _documents[_name]; } /** - * @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 - * @param _log data attached to the transfer by controller to emit in event + * @notice Internal function to know whether the controller functionality + * allowed or not. + * @return bool `true` when controller address is non-zero otherwise return `false`. */ - function forceBurn(address _from, uint256 _value, bytes memory _data, bytes memory _log) public onlyController { - bool verified = _checkAndBurn(_from, _value, _data); - emit ForceBurn(msg.sender, _from, _value, verified, _log); + function _isControllable() internal view returns (bool) { + return !controllerDisabled; } /** - * @notice Returns the version of the SecurityToken + * @notice In order to provide transparency over whether `controllerTransfer` / `controllerRedeem` are useable + * or not `isControllable` function will be used. + * @dev If `isControllable` returns `false` then it always return `false` and + * `controllerTransfer` / `controllerRedeem` will always revert. + * @return bool `true` when controller address is non-zero otherwise return `false`. */ - function getVersion() external view returns(uint8[] memory) { - uint8[] memory _version = new uint8[](3); - _version[0] = securityTokenVersion.major; - _version[1] = securityTokenVersion.minor; - _version[2] = securityTokenVersion.patch; - return _version; + function isControllable() external view returns (bool) { + return _isControllable(); + } + + /** + * @notice This function allows an authorised address to transfer tokens between any two token holders. + * The transfer must still respect the balances of the token holders (so the transfer must be for at most + * `balanceOf(_from)` tokens) and potentially also need to respect other transfer restrictions. + * @dev This function can only be executed by the `controller` address. + * @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 + * @param _data data to validate the transfer. (It is not used in this reference implementation + * because use of `_data` parameter is implementation specific). + * @param _operatorData data attached to the transfer by controller to emit in event. (It is more like a reason string + * for calling this function (aka force transfer) which provides the transparency on-chain). + */ + function controllerTransfer(address _from, address _to, uint256 _value, bytes calldata _data, bytes calldata _operatorData) external onlyController { + require(_isControllable()); + _updateTransfer(_from, _to, _value, _data); + _transfer(_from, _to, _value); + emit ControllerTransfer(msg.sender, _from, _to, _value, _data, _operatorData); + } + + /** + * @notice This function allows an authorised address to redeem tokens for any token holder. + * The redemption must still respect the balances of the token holder (so the redemption must be for at most + * `balanceOf(_tokenHolder)` tokens) and potentially also need to respect other transfer restrictions. + * @dev This function can only be executed by the `controller` address. + * @param _tokenHolder The account whose tokens will be redeemed. + * @param _value uint256 the amount of tokens need to be redeemed. + * @param _data data to validate the transfer. (It is not used in this reference implementation + * because use of `_data` parameter is implementation specific). + * @param _operatorData data attached to the transfer by controller to emit in event. (It is more like a reason string + * for calling this function (aka force transfer) which provides the transparency on-chain). + */ + function controllerRedeem(address _tokenHolder, uint256 _value, bytes calldata _data, bytes calldata _operatorData) external onlyController { + require(_isControllable()); + _checkAndBurn(_tokenHolder, _value, _data); + emit ControllerRedemption(msg.sender, _tokenHolder, _value, _data, _operatorData); + } + + function _implementation() internal view returns(address) { + return delegate; + } + + function updateFromRegistry() public onlyOwner { + moduleRegistry = PolymathRegistry(polymathRegistry).getAddress("ModuleRegistry"); + securityTokenRegistry = PolymathRegistry(polymathRegistry).getAddress("SecurityTokenRegistry"); + featureRegistry = PolymathRegistry(polymathRegistry).getAddress("FeatureRegistry"); + polyToken = PolymathRegistry(polymathRegistry).getAddress("PolyToken"); } } diff --git a/contracts/tokens/SecurityTokenStorage.sol b/contracts/tokens/SecurityTokenStorage.sol new file mode 100644 index 000000000..293bb4727 --- /dev/null +++ b/contracts/tokens/SecurityTokenStorage.sol @@ -0,0 +1,112 @@ +pragma solidity ^0.5.0; + +contract SecurityTokenStorage { + + uint8 constant PERMISSION_KEY = 1; + uint8 constant TRANSFER_KEY = 2; + uint8 constant MINT_KEY = 3; + uint8 constant CHECKPOINT_KEY = 4; + uint8 constant BURN_KEY = 5; + uint8 constant DATA_KEY = 6; + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) + + ////////////////////////// + /// Document datastructure + ////////////////////////// + + struct Document { + bytes32 docHash; // Hash of the document + uint256 lastModified; // Timestamp at which document details was last modified + string uri; // URI of the document that exist off-chain + } + + // Used to hold the semantic version data + struct SemanticVersion { + uint8 major; + uint8 minor; + uint8 patch; + } + + // Struct for module data + struct ModuleData { + bytes32 name; + address module; + address moduleFactory; + bool isArchived; + uint8[] moduleTypes; + uint256[] moduleIndexes; + uint256 nameIndex; + bytes32 label; + } + + // Structures to maintain checkpoints of balances for governance / dividends + struct Checkpoint { + uint256 checkpointId; + uint256 value; + } + + // Address of the controller which is a delegated entity + // set by the issuer/owner of the token + address public controller; + + address public polymathRegistry; + address public moduleRegistry; + address public securityTokenRegistry; + address public featureRegistry; + address public polyToken; + address public delegate; + // Address of the data store used to store shared data + address public dataStore; + + uint256 public granularity; + + // Value of current checkpoint + uint256 public currentCheckpointId; + + // off-chain data + string public tokenDetails; + + // Used to permanently halt controller actions + bool public controllerDisabled = false; + + // Used to temporarily halt all transactions + bool public transfersFrozen; + + // Number of investors with non-zero balance + uint256 public holderCount; + + // Variable which tells whether issuance is ON or OFF forever + // Implementers need to implement one more function to reset the value of `issuance` variable + // to false. That function is not a part of the standard (EIP-1594) as it is depend on the various factors + // issuer, followed compliance rules etc. So issuers have the choice how they want to close the issuance. + bool internal issuance = true; + + // Array use to store all the document name present in the contracts + bytes32[] _docNames; + + // Times at which each checkpoint was created + uint256[] checkpointTimes; + + SemanticVersion securityTokenVersion; + + // Records added modules - module list should be order agnostic! + mapping(uint8 => address[]) modules; + + // Records information about the module + mapping(address => ModuleData) modulesToData; + + // Records added module names - module list should be order agnostic! + mapping(bytes32 => address[]) names; + + // Mapping of checkpoints that relate to total supply + mapping (uint256 => uint256) checkpointTotalSupply; + + // Map each investor to a series of checkpoints + mapping(address => Checkpoint[]) checkpointBalances; + + // mapping to store the documents details in the document + mapping(bytes32 => Document) internal _documents; + // mapping to store the document name indexes + mapping(bytes32 => uint256) internal _docIndexes; + +} \ No newline at end of file diff --git a/docs/ethereum_status_codes.md b/docs/ethereum_status_codes.md new file mode 100644 index 000000000..60a2ff0d9 --- /dev/null +++ b/docs/ethereum_status_codes.md @@ -0,0 +1,46 @@ + +# For ERC1400 + +| Code | Reason | +| ------ | ------------------------------------------------------------- | +| `0x50` | transfer failure | +| `0x51` | transfer success | +| `0x52` | insufficient balance | +| `0x53` | insufficient allowance | +| `0x54` | transfers halted (contract paused) | +| `0x55` | funds locked (lockup period) | +| `0x56` | invalid sender | +| `0x57` | invalid receiver | +| `0x58` | invalid operator (transfer agent) | +| `0x59` | | +| `0x5a` | | +| `0x5b` | | +| `0x5a` | | +| `0x5b` | | +| `0x5c` | | +| `0x5d` | | +| `0x5e` | | +| `0x5f` | token meta or info + +# For Application specific (Polymath) + +| Code | Reason | +| ------ | ------------------------------------------------------------- | +| `0xA0` | Not affected | +| `0xA1` | Success | +| `0xA2` | Max holders reach | +| `0xA3` | Manual Approval Expired | +| `0xA4` | funds limit reached | +| `0xA5` | Tx Volume limit reached | +| `0xA6` | Blacklisted tx | +| `0xA7` | funds locked (lockup period) | +| `0xA8` | Invalid granularity | +| `0xA9` | | +| `0xAa` | | +| `0xAb` | | +| `0xAa` | | +| `0xAb` | | +| `0xAc` | | +| `0xAd` | | +| `0xAe` | | +| `0xAf` | token meta or info | diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 0cc03e0d5..a0f718c20 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -29,6 +29,7 @@ const StableOracle = artifacts.require("./StableOracle.sol"); const TokenLib = artifacts.require("./TokenLib.sol"); const SecurityToken = artifacts.require("./tokens/SecurityToken.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); +const STGetter = artifacts.require('./STGetter.sol'); const DataStoreLogic = artifacts.require('./DataStore.sol'); const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const VolumeRestrictionTMFactory = artifacts.require('./VolumeRestrictionTMFactory.sol') @@ -215,6 +216,7 @@ module.exports = function(deployer, network, accounts) { deployer.link(VolumeRestrictionLib, VolumeRestrictionTMLogic); deployer.link(TokenLib, SecurityToken); deployer.link(TokenLib, STFactory); + deployer.link(TokenLib, STGetter); // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) return deployer.deploy(ModuleRegistry, { from: PolymathAccount }); }) @@ -348,9 +350,13 @@ module.exports = function(deployer, network, accounts) { from: PolymathAccount }); }) + .then(() => { + // Deploy the STGetter contract (Logic contract that have the getters of the securityToken) + return deployer.deploy(STGetter, { from: PolymathAccount }); + }) .then(() => { // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. - return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, DataStoreFactory.address, { from: PolymathAccount }); + return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, DataStoreFactory.address, STGetter.address, { from: PolymathAccount }); }) .then(() => { // K) Deploy the FeatureRegistry contract to control feature switches @@ -519,11 +525,9 @@ module.exports = function(deployer, network, accounts) { return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, { from: PolymathAccount }); }) .then(() => { + return deployer.deploy(SecurityToken, "a", "a", 18, 1, "a", polymathRegistry.address, STGetter.address, { from: PolymathAccount }); return polymathRegistry.changeAddress("StablePolyUsdOracle", StablePOLYOracle, { from: PolymathAccount }); }) - .then(() => { - return deployer.deploy(SecurityToken, "a", "a", 18, 1, "a", polymathRegistry.address, { from: PolymathAccount }); - }) .then(() => { console.log("\n"); console.log(` diff --git a/module-labeling b/module-labeling deleted file mode 100644 index 0026fe372..000000000 --- a/module-labeling +++ /dev/null @@ -1 +0,0 @@ -Branch 'module-labeling' set up to track remote branch 'module-labeling' from 'origin'. diff --git a/package.json b/package.json index 4c45a49ab..ede090493 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "readline-sync": "^1.4.9", "request": "^2.88.0", "request-promise": "^4.2.2", + "solc": "^0.5.2", "truffle-contract": "^3.0.4", "truffle-hdwallet-provider-privkey": "0.2.0", "web3": "1.0.0-beta.35" diff --git a/scripts/compareStorageLayout.js b/scripts/compareStorageLayout.js index 92d43a56f..382efdedf 100644 --- a/scripts/compareStorageLayout.js +++ b/scripts/compareStorageLayout.js @@ -6,11 +6,13 @@ const path = require("path"); const util = require("util"); const exec = util.promisify(require("child_process").exec); +console.log(`Mandatory: Solc cli tool should be installed globally`); prompt.start(); prompt.get(["LogicContract", "ProxyContract"], async (err, result) => { - let logicContract; - let proxyContract; + let temp; + let logicFilePath; + let proxyFilePath; const fileList = walkSync("./contracts", []); @@ -20,26 +22,22 @@ prompt.get(["LogicContract", "ProxyContract"], async (err, result) => { console.log("Contracts exists \n"); await flatContracts(paths); - + let temp; + let logicFilePath = `./flat/${path.basename(paths[0])}`; + let proxyFilePath = `./flat/${path.basename(paths[1])}`; + 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"); + temp = logicFilePath; + logicFilePath = proxyFilePath; + proxyFilePath = temp; } - let logicInput = { - contracts: logicContract - }; - let proxyInput = { - contracts: proxyContract - }; + let logicAST = await getAST(logicFilePath); + let proxyAST = await getAST(proxyFilePath); + // Deleting the temp folder (no longer required) + await flushTemp(); - console.log(compareStorageLayouts(parseContract(logicInput), parseContract(proxyInput))); + console.log(compareStorageLayouts(parseContract(logicAST), parseContract(proxyAST))); } else { console.log("Contracts doesn't exists"); } @@ -74,10 +72,9 @@ function compareStorageLayouts(logicLayout, proxyLayout) { } function parseContract(input) { - var output = solc.compile({ sources: input }, 1, _.noop); + const elements = []; - const AST = output.sources.contracts.AST; - // console.log(AST); + const AST = input; traverseAST(AST, elements); // console.log(elements); @@ -138,3 +135,12 @@ async function flatContracts(_paths, _logic) { } await Promise.all(promises); } + +async function getAST(_filePath) { + await exec(`solc -o temp --ast-json ${_filePath}`, {maxBuffer: 1024 * 1000}); + return JSON.parse(fs.readFileSync(`./temp/${path.basename(_filePath)}_json.ast`, "utf8").toString()); +} + +async function flushTemp() { + await exec(`rm -rf temp`); +} \ No newline at end of file diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 8392f189a..1766fd8be 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -10,6 +10,7 @@ const CappedSTO = artifacts.require("./CappedSTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -60,6 +61,9 @@ contract("CappedSTO", async (accounts) => { let I_STRProxied; let I_MRProxied; let I_STRGetter; + let I_STGetter; + let stGetter_eth; + let stGetter_poly; let pauseTime; // SecurityToken Details for funds raise Type ETH @@ -129,8 +133,9 @@ contract("CappedSTO", async (accounts) => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied, - I_STRGetter + I_STRProxied, + I_STRGetter, + I_STGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory @@ -175,7 +180,7 @@ contract("CappedSTO", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); I_SecurityToken_ETH = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter_eth = await STGetter.at(I_SecurityToken_ETH.address); const log = (await I_SecurityToken_ETH.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), transferManagerKey); @@ -183,12 +188,12 @@ contract("CappedSTO", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; + let moduleData = (await stGetter_eth.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should mint the tokens before attaching the STO", async () => { - await catchRevert(I_SecurityToken_ETH.mint(address_zero, new BN(new BN(web3.utils.toWei("1"))), { from: token_owner })); + await catchRevert(I_SecurityToken_ETH.issue(address_zero, new BN(new BN(web3.utils.toWei("1"))), "0x0", { from: token_owner })); }); it("Should fail to launch the STO due to security token doesn't have the sufficient POLY", async () => { @@ -623,7 +628,7 @@ contract("CappedSTO", async (accounts) => { assert.equal(tx.logs[2].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); I_SecurityToken_POLY = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter_poly = await STGetter.at(I_SecurityToken_POLY.address); const log = (await I_SecurityToken_POLY.getPastEvents('ModuleAdded', {filter: {from: blockNo}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -632,7 +637,7 @@ contract("CappedSTO", async (accounts) => { }); it("POLY: Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; + let moduleData = (await stGetter_poly.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 20a1488ce..96066453e 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -2,9 +2,11 @@ import latestTime from "./helpers/latestTime"; import { duration, ensureException, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { setUpPolymathNetwork } from "./helpers/createInstances"; +import { catchRevert } from "./helpers/exceptions"; const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -19,6 +21,7 @@ contract("Checkpoints", async function(accounts) { let account_investor2; let account_investor3; let account_investor4; + let account_controller; let message = "Transaction Should Fail!"; @@ -45,6 +48,8 @@ contract("Checkpoints", async function(accounts) { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -70,7 +75,7 @@ contract("Checkpoints", async function(accounts) { account_issuer = accounts[1]; token_owner = account_issuer; - + account_controller = accounts[3]; account_investor1 = accounts[6]; account_investor2 = accounts[7]; account_investor3 = accounts[8]; @@ -91,7 +96,8 @@ contract("Checkpoints", async function(accounts) { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // Printing all the contract addresses @@ -126,7 +132,7 @@ contract("Checkpoints", async function(accounts) { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -134,12 +140,18 @@ contract("Checkpoints", async function(accounts) { 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 set controller to token owner --failed not allowed", async () => { + await catchRevert( + I_SecurityToken.setController(token_owner, { from: token_owner }) + ); }); + it("Should set the tcontroller", async() => { + await I_SecurityToken.setController(account_controller, {from: token_owner}); + }) + it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -165,7 +177,7 @@ contract("Checkpoints", async function(accounts) { ); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("10", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); @@ -191,7 +203,7 @@ contract("Checkpoints", async function(accounts) { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); @@ -217,7 +229,7 @@ contract("Checkpoints", async function(accounts) { // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("10", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("10", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("10", "ether")).toString()); }); @@ -242,7 +254,7 @@ contract("Checkpoints", async function(accounts) { JSON.stringify(totalSupply) ); await I_SecurityToken.createCheckpoint({ from: token_owner }); - let checkpointTimes = await I_SecurityToken.getCheckpointTimes(); + let checkpointTimes = await stGetter.getCheckpointTimes(); assert.equal(checkpointTimes.length, j + 1); console.log("Checkpoint Times: " + checkpointTimes); let txs = Math.floor(Math.random() * 3); @@ -289,7 +301,7 @@ contract("Checkpoints", async function(accounts) { minter = account_investor3; } console.log("Minting: " + n.toString() + " to: " + minter); - await I_SecurityToken.mint(minter, n, { from: token_owner }); + await I_SecurityToken.issue(minter, n, "0x0", { from: token_owner }); } if (Math.random() > 0.5) { let n = new BN(Math.random().toFixed(10)).mul(new BN(10).pow(new BN(17))); @@ -308,14 +320,14 @@ contract("Checkpoints", async function(accounts) { n = burnerBalance.div(new BN(2)); } console.log("Burning: " + n.toString() + " from: " + burner); - await I_SecurityToken.forceBurn(burner, n, "0x0", "0x0", { from: token_owner }); + await I_SecurityToken.controllerRedeem(burner, n, "0x0", "0x0", { from: account_controller }); } console.log("Checking Interim..."); for (let k = 0; k < cps.length; k++) { - let balance1 = new BN(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); - let balance2 = new BN(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); - let balance3 = new BN(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); - let totalSupply = new BN(await I_SecurityToken.totalSupplyAt(k + 1)); + let balance1 = new BN(await stGetter.balanceOfAt(account_investor1, k + 1)); + let balance2 = new BN(await stGetter.balanceOfAt(account_investor2, k + 1)); + let balance3 = new BN(await stGetter.balanceOfAt(account_investor3, k + 1)); + let totalSupply = new BN(await stGetter.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])); @@ -328,10 +340,10 @@ contract("Checkpoints", async function(accounts) { } console.log("Checking..."); for (let k = 0; k < cps.length; k++) { - let balance1 = new BN(await I_SecurityToken.balanceOfAt(account_investor1, k + 1)); - let balance2 = new BN(await I_SecurityToken.balanceOfAt(account_investor2, k + 1)); - let balance3 = new BN(await I_SecurityToken.balanceOfAt(account_investor3, k + 1)); - let totalSupply = new BN(await I_SecurityToken.totalSupplyAt(k + 1)); + let balance1 = new BN(await stGetter.balanceOfAt(account_investor1, k + 1)); + let balance2 = new BN(await stGetter.balanceOfAt(account_investor2, k + 1)); + let balance3 = new BN(await stGetter.balanceOfAt(account_investor3, k + 1)); + let totalSupply = new BN(await stGetter.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])); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 64ac16798..7302fd99a 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -9,6 +9,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const CountTransferManagerFactory = artifacts.require("./CountTransferManagerFactory.sol"); const CountTransferManager = artifacts.require("./CountTransferManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -50,6 +51,9 @@ contract("CountTransferManager", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; + let stGetter2; // SecurityToken Details const name = "Team"; @@ -101,7 +105,8 @@ contract("CountTransferManager", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the CountTransferManager @@ -142,7 +147,7 @@ contract("CountTransferManager", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -151,7 +156,7 @@ contract("CountTransferManager", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -221,7 +226,7 @@ contract("CountTransferManager", async (accounts) => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -247,7 +252,7 @@ contract("CountTransferManager", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); @@ -272,7 +277,7 @@ contract("CountTransferManager", async (accounts) => { "Failed in adding the investor in whitelist" ); - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("3", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("3", "ether")), "0x0", { from: token_owner }); await revertToSnapshot(snapId); }); @@ -296,13 +301,13 @@ contract("CountTransferManager", async (accounts) => { "Failed in adding the investor in whitelist" ); - await catchRevert(I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("3", "ether")), { from: token_owner })); + await catchRevert(I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("3", "ether")), "0x0", { from: token_owner })); }); 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, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("4", "ether")).toString()); }); @@ -360,8 +365,8 @@ contract("CountTransferManager", async (accounts) => { let tx2 = await I_STRProxied.generateSecurityToken(name, symbol2, tokenDetails, false, { from: token_owner }); I_SecurityToken2 = await SecurityToken.at(tx2.logs[2].args._securityTokenAddress); - - let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + stGetter2 = await STGetter.at(I_SecurityToken2.address); + let moduleData = (await stGetter2.getModulesByType(2))[0]; I_GeneralTransferManager2 = await GeneralTransferManager.at(moduleData); }); @@ -414,14 +419,14 @@ contract("CountTransferManager", async (accounts) => { await increaseTime(5000); // Add 3 holders to the token - await I_SecurityToken2.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - await I_SecurityToken2.mint(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); - await I_SecurityToken2.mint(account_investor3, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken2.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); + await I_SecurityToken2.issue(account_investor2, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); + await I_SecurityToken2.issue(account_investor3, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + let moduleData = (await stGetter2.getModulesByType(2))[0]; I_GeneralTransferManager2 = await GeneralTransferManager.at(moduleData); }); @@ -449,11 +454,11 @@ contract("CountTransferManager", async (accounts) => { 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); - let investorCount = await I_SecurityToken2.holderCount({ from: account_investor2 }); + let investorCount = await stGetter2.holderCount({ 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)).toString(), amount.toString(), { from: account_investor2 }); - assert(await I_SecurityToken2.holderCount({ from: account_investor2 }), investorCount); + assert(await stGetter2.holderCount({ from: account_investor2 }), investorCount); }); }); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 9a78e96e1..656060a0a 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -9,6 +9,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const ERC20DividendCheckpoint = artifacts.require("./ERC20DividendCheckpoint"); const GeneralPermissionManager = artifacts.require("GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -52,6 +53,8 @@ contract("ERC20DividendCheckpoint", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -109,7 +112,8 @@ contract("ERC20DividendCheckpoint", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; [P_ERC20DividendCheckpointFactory] = await deployERC20DividendAndVerifyed( @@ -153,7 +157,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._types[0].toNumber(), 2); @@ -161,7 +165,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -230,7 +234,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -256,7 +260,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); @@ -397,7 +401,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_temp, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_temp)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -463,7 +467,7 @@ contract("ERC20DividendCheckpoint", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("7", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("7", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); @@ -909,10 +913,10 @@ contract("ERC20DividendCheckpoint", async (accounts) => { assert.equal(info[4][2].toString(), new BN(web3.utils.toWei("0.8", "ether")).toString(), "claim match"); assert.equal(info[4][3].toString(), new BN(web3.utils.toWei("7", "ether")).toString(), "claim match"); - assert.equal(info[5][0].toString(), (await I_SecurityToken.balanceOfAt(account_investor1, new BN(4))).toString(), "balance match"); - assert.equal(info[5][1].toString(), (await I_SecurityToken.balanceOfAt(account_investor2, new BN(4))).toString(), "balance match"); - assert.equal(info[5][2].toString(), (await I_SecurityToken.balanceOfAt(account_temp, new BN(4))).toString(), "balance match"); - assert.equal(info[5][3].toString(), (await I_SecurityToken.balanceOfAt(account_investor3, new BN(4))).toString(), "balance match"); + assert.equal(info[5][0].toString(), (await stGetter.balanceOfAt(account_investor1, new BN(4))).toString(), "balance match"); + assert.equal(info[5][1].toString(), (await stGetter.balanceOfAt(account_investor2, new BN(4))).toString(), "balance match"); + assert.equal(info[5][2].toString(), (await stGetter.balanceOfAt(account_temp, new BN(4))).toString(), "balance match"); + assert.equal(info[5][3].toString(), (await stGetter.balanceOfAt(account_investor3, new BN(4))).toString(), "balance match"); let issuerBalance = new BN(await I_PolyToken.balanceOf(wallet)); @@ -1138,10 +1142,10 @@ contract("ERC20DividendCheckpoint", async (accounts) => { 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].toString(), (await I_SecurityToken.balanceOfAt.call(account_investor1, checkpointID)).toString(), "balance match"); - assert.equal(info[1][1].toString(), (await I_SecurityToken.balanceOfAt.call(account_investor2, checkpointID)).toString(), "balance match"); - assert.equal(info[1][2].toString(), (await I_SecurityToken.balanceOfAt.call(account_temp, checkpointID)).toString(), "balance match"); - assert.equal(info[1][3].toString(), (await I_SecurityToken.balanceOfAt.call(account_investor3, checkpointID)).toString(), "balance match"); + assert.equal(info[1][0].toString(), (await stGetter.balanceOfAt.call(account_investor1, checkpointID)).toString(), "balance match"); + assert.equal(info[1][1].toString(), (await stGetter.balanceOfAt.call(account_investor2, checkpointID)).toString(), "balance match"); + assert.equal(info[1][2].toString(), (await stGetter.balanceOfAt.call(account_temp, checkpointID)).toString(), "balance match"); + assert.equal(info[1][3].toString(), (await stGetter.balanceOfAt.call(account_investor3, checkpointID)).toString(), "balance match"); assert.equal(info[2][0].toNumber(), 0, "withholding match"); assert.equal(info[2][1].toString(), new BN((10 * 10 ** 16).toString()).toString(), "withholding match"); assert.equal(info[2][2].toString(), new BN((20 * 10 ** 16).toString()).toString(), "withholding match"); diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index d59e16ce1..3c379ac43 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -10,6 +10,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const EtherDividendCheckpoint = artifacts.require("./EtherDividendCheckpoint"); const GeneralPermissionManager = artifacts.require("GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -54,6 +55,8 @@ contract("EtherDividendCheckpoint", async (accounts) => { let I_MRProxied; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -105,7 +108,8 @@ contract("EtherDividendCheckpoint", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; [P_EtherDividendCheckpointFactory] = await deployEtherDividendAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether")); @@ -146,7 +150,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -155,7 +159,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -224,7 +228,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -250,7 +254,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); @@ -379,7 +383,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { 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, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_temp, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_temp)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -433,7 +437,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("7", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("7", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); }); @@ -733,7 +737,7 @@ contract("EtherDividendCheckpoint", async (accounts) => { // Jump time await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(I_PolyToken.address, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(I_PolyToken.address, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("7", "ether")).toString()); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index b339376f2..a4f8bcc0d 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -9,6 +9,7 @@ import { setUpPolymathNetwork, deployGPMAndVerifyed } from "./helpers/createInst const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter"); const Web3 = require("web3"); const BN = Web3.utils.BN; @@ -51,6 +52,8 @@ contract("GeneralPermissionManager", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -101,7 +104,8 @@ contract("GeneralPermissionManager", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory @@ -143,7 +147,7 @@ contract("GeneralPermissionManager", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -152,7 +156,7 @@ contract("GeneralPermissionManager", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -263,9 +267,9 @@ contract("GeneralPermissionManager", async (accounts) => { it("Security token should deny all permission if all permission managers are disabled", async () => { await I_SecurityToken.archiveModule(I_GeneralPermissionManager.address, { from: token_owner }); - assert.isFalse(await I_SecurityToken.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))); + assert.isFalse(await stGetter.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))); await I_SecurityToken.unarchiveModule(I_GeneralPermissionManager.address, { from: token_owner }); - assert.isTrue(await I_SecurityToken.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))); + assert.isTrue(await stGetter.checkPermission.call(account_delegate, I_GeneralTransferManager.address, web3.utils.fromAscii("WHITELIST"))); }); it("Should fail to remove the delegate -- failed because unauthorized msg.sender", async () => { diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index b9462c906..a88b35370 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -11,6 +11,7 @@ const DummySTO = artifacts.require("./DummySTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -58,6 +59,8 @@ contract("GeneralTransferManager", async (accounts) => { let I_PolymathRegistry; let P_GeneralTransferManagerFactory; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -130,7 +133,8 @@ contract("GeneralTransferManager", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, 0); @@ -173,7 +177,7 @@ contract("GeneralTransferManager", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -182,7 +186,7 @@ contract("GeneralTransferManager", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -207,7 +211,7 @@ contract("GeneralTransferManager", async (accounts) => { let investors = await I_GeneralTransferManager.getInvestors(0, 1); assert.equal(investors[0], account_investor1); assert.equal(investors[1], account_investor2); - let investorCount = await I_SecurityToken.getInvestorCount(); + let investorCount = await stGetter.getInvestorCount(); assert.equal(investorCount.toNumber(), 2); let allInvestorFlags = await I_GeneralTransferManager.getAllInvestorFlags(); assert.deepEqual(investors, allInvestorFlags[0]); @@ -283,11 +287,11 @@ contract("GeneralTransferManager", async (accounts) => { it("Should mint the tokens to the affiliates", async () => { console.log(` - Estimate gas cost for minting the tokens: ${await I_SecurityToken.mintMulti.estimateGas([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { + Estimate gas cost for minting the tokens: ${await I_SecurityToken.issueMulti.estimateGas([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { from: account_issuer })} `) - await I_SecurityToken.mintMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { + await I_SecurityToken.issueMulti([account_affiliates1, account_affiliates2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(10).pow(new BN(20))], { from: account_issuer, gas: 6000000 }); diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 8adb680b8..76733d8fe 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -5,7 +5,6 @@ const MockOracle = artifacts.require("./MockOracle.sol"); const StableOracle = artifacts.require("./StableOracle.sol"); const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); -const SecurityToken = artifacts.require("./SecurityToken.sol"); const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const CappedSTO = artifacts.require("./CappedSTO.sol"); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); @@ -42,6 +41,7 @@ const DummySTO = artifacts.require("./DummySTO.sol"); const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); const STRGetter = artifacts.require("./STRGetter.sol"); const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const DataStoreLogic = artifacts.require('./DataStore.sol'); const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); const SignedTransferManagerFactory = artifacts.require("./SignedTransferManagerFactory"); @@ -101,6 +101,7 @@ let I_VestingEscrowWalletLogic; let I_STRProxied; let I_MRProxied; let I_STRGetter; +let I_STGetter; let I_SignedTransferManagerFactory; let I_USDOracle; let I_POLYOracle; @@ -150,6 +151,7 @@ export async function setUpPolymathNetwork(account_polymath, token_owner) { I_SecurityTokenRegistryProxy, I_STRProxied, I_STRGetter, + I_STGetter, I_USDOracle, I_POLYOracle, I_StablePOLYOracle @@ -174,7 +176,8 @@ export async function deployPolyRegistryAndPolyToken(account_polymath, token_own 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(); + I_PolyToken = await PolyTokenFaucet.new({ from: account_polymath }); + await I_PolyToken.getTokens(new BN(10000).mul(new BN(10).pow(new BN(18))), token_owner); await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, { from: account_polymath }); @@ -232,13 +235,14 @@ async function deployGTM(account_polymath) { } async function deploySTFactory(account_polymath) { + I_STGetter = await STGetter.new({from: account_polymath}); let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, I_STGetter.address, { from: account_polymath }); assert.notEqual(I_STFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", "STFactory contract was not deployed"); - return new Array(I_STFactory); + return new Array(I_STFactory, I_STGetter); } async function deploySTR(account_polymath) { diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 78291f7dd..fda71fc93 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -9,6 +9,7 @@ const CappedSTO = artifacts.require("./CappedSTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -52,6 +53,8 @@ contract("Issuance", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -111,7 +114,8 @@ contract("Issuance", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -157,7 +161,7 @@ contract("Issuance", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -166,7 +170,7 @@ contract("Issuance", async (accounts) => { }); it("POLYMATH: Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + let moduleData = (await stGetter.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -220,7 +224,7 @@ contract("Issuance", async (accounts) => { it("Should add the delegate with permission", async () => { //First attach a permission manager to the token await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(0), { from: account_polymath }); - let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; + let moduleData = (await stGetter.getModulesByType(permissionManagerKey))[0]; I_GeneralPermissionManager = await GeneralPermissionManager.at(moduleData); // Add permission to the deletgate (A regesteration process) await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_polymath }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 2d3244e38..c7509043c 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -10,6 +10,7 @@ const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); const CountTransferManager = artifacts.require("./CountTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -55,6 +56,9 @@ contract("ManualApprovalTransferManager", accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -104,7 +108,9 @@ contract("ManualApprovalTransferManager", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -152,7 +158,7 @@ contract("ManualApprovalTransferManager", accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -161,7 +167,7 @@ contract("ManualApprovalTransferManager", accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -191,7 +197,7 @@ contract("ManualApprovalTransferManager", accounts => { await increaseTime(5000); currentTime = new BN(await latestTime()); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei("30", "ether"), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("30", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), web3.utils.toWei("30", "ether")); }); @@ -217,7 +223,7 @@ contract("ManualApprovalTransferManager", accounts => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, web3.utils.toWei("10", "ether"), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), web3.utils.toWei("10", "ether")); }); @@ -261,15 +267,14 @@ contract("ManualApprovalTransferManager", accounts => { ); I_ManualApprovalTransferManager = await 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 () => { + + it("Cannot call executeTransfer on the TM directly", async () => { await catchRevert( - I_ManualApprovalTransferManager.verifyTransfer( + I_ManualApprovalTransferManager.executeTransfer( account_investor4, account_investor4, web3.utils.toWei("2", "ether"), "0x0", - true, { from: token_owner } ) ); @@ -281,7 +286,6 @@ contract("ManualApprovalTransferManager", accounts => { account_investor4, web3.utils.toWei("2", "ether"), "0x0", - false, { from: token_owner } ); }); @@ -307,7 +311,7 @@ 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("10", "ether"), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("10", "ether")),"0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), web3.utils.toWei("10", "ether")); // Unpause at the transferManager level @@ -395,20 +399,26 @@ contract("ManualApprovalTransferManager", accounts => { }) it("Check verifyTransfer without actually transferring", async () => { - let verified = await I_SecurityToken.verifyTransfer.call( - account_investor1, + let verified = await I_SecurityToken.canTransfer.call( account_investor4, web3.utils.toWei("2", "ether"), - "0x0" + "0x0", + { + from: account_investor1 + } ); - console.log(JSON.stringify(verified)); - assert.equal(verified, true); + console.log(JSON.stringify(verified[0])); + assert.equal(verified[0], true); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("4", "ether"), "0x0"); - assert.equal(verified, false); + verified = await I_SecurityToken.canTransfer.call(account_investor4, web3.utils.toWei("4", "ether"), "0x0", { + from: account_investor1 + }); + assert.equal(verified[0], false); - verified = await I_SecurityToken.verifyTransfer.call(account_investor1, account_investor4, web3.utils.toWei("1", "ether"), "0x0"); - assert.equal(verified, true); + verified = await I_SecurityToken.canTransfer.call(account_investor4, web3.utils.toWei("1", "ether"), "0x0", { + from: account_investor1 + }); + assert.equal(verified[0], true); }); it("Should fail to sell the tokens more than the allowance", async() => { diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 036949f9a..c13a46929 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -17,6 +17,7 @@ const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManage const MockFactory = artifacts.require("./MockFactory.sol"); const TestSTOFactory = artifacts.require("./TestSTOFactory.sol"); const ReclaimTokens = artifacts.require("./ReclaimTokens.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -64,6 +65,8 @@ contract("ModuleRegistry", async (accounts) => { let I_PolymathRegistry; let I_SecurityToken2; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -123,7 +126,8 @@ contract("ModuleRegistry", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: account_polymath}); diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index eafc4fd42..04222882a 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -8,6 +8,7 @@ const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const PercentageTransferManager = artifacts.require("./PercentageTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -47,6 +48,8 @@ contract("PercentageTransferManager", async (accounts) => { let I_PolyToken; let I_STRGetter; let I_PolymathRegistry; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -117,7 +120,8 @@ contract("PercentageTransferManager", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -168,7 +172,7 @@ contract("PercentageTransferManager", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -177,7 +181,7 @@ contract("PercentageTransferManager", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -218,7 +222,7 @@ contract("PercentageTransferManager", async (accounts) => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -244,7 +248,7 @@ contract("PercentageTransferManager", async (accounts) => { ); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -309,7 +313,7 @@ contract("PercentageTransferManager", async (accounts) => { // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -334,14 +338,14 @@ contract("PercentageTransferManager", async (accounts) => { await catchRevert(I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei("2", "ether")), { from: account_investor1 })); }); - it("Should not be able to mint token amount over limit", async () => { - await catchRevert(I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("100", "ether")), { from: token_owner })); + it("Should not be able to issue token amount over limit", async () => { + await catchRevert(I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("100", "ether")), "0x0", { from: token_owner })); }); 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, new BN(web3.utils.toWei("100", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("100", "ether")), "0x0", { from: token_owner }); // trying to call it again with the same value. should fail await catchRevert(I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner })); await revertToSnapshot(snapId); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index c323fd1b3..300850352 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -9,6 +9,7 @@ const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PreSaleSTO = artifacts.require("./PreSaleSTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -50,6 +51,8 @@ contract("PreSaleSTO", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details for funds raise Type ETH const name = "Team"; @@ -101,7 +104,8 @@ contract("PreSaleSTO", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 4: Deploy the PreSaleSTOFactory @@ -144,7 +148,7 @@ contract("PreSaleSTO", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -153,7 +157,7 @@ contract("PreSaleSTO", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + let moduleData = (await stGetter.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index fd2fbeb7e..51680c96d 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -12,6 +12,7 @@ const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock.sol"); const STFactory = artifacts.require("./STFactory.sol"); const STRGetter = artifacts.require('./STRGetter.sol'); +const STGetter = artifacts.require("./STGetter.sol"); const DataStoreLogic = artifacts.require('./DataStore.sol'); const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); @@ -61,6 +62,8 @@ contract("SecurityTokenRegistry", async (accounts) => { let I_MRProxied; let I_STRGetter; let I_Getter; + let I_STGetter; + let stGetter; let I_USDOracle; let I_POLYOracle; let I_StablePOLYOracle; @@ -124,6 +127,7 @@ contract("SecurityTokenRegistry", async (accounts) => { I_SecurityTokenRegistryProxy, I_STRProxied, I_STRGetter, + I_STGetter, I_USDOracle, I_POLYOracle, I_StablePOLYOracle @@ -570,7 +574,7 @@ contract("SecurityTokenRegistry", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTrasnferManager module get added successfully or not @@ -634,10 +638,11 @@ contract("SecurityTokenRegistry", async (accounts) => { describe("Generate SecurityToken v2", async () => { it("Should deploy the st version 2", async () => { // Step 7: Deploy the STFactory contract + I_STGetter = await STGetter.new(); let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); - I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); + I_STFactory002 = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, I_STGetter.address, { from: account_polymath }); assert.notEqual( I_STFactory002.address.valueOf(), diff --git a/test/o_security_token.js b/test/o_security_token.js index 38fb10c81..2d0808112 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -17,6 +17,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const MockRedemptionManager = artifacts.require("./MockRedemptionManager.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -47,6 +48,11 @@ contract("SecurityToken", async (accounts) => { let ID_snap; const message = "Transaction Should Fail!!"; + const uri = "https://www.gogl.bts.fly"; + const docHash = web3.utils.utf8ToHex("hello"); + + const empty_hash = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Contract Instance Declaration let I_GeneralPermissionManagerFactory; @@ -69,6 +75,8 @@ contract("SecurityToken", async (accounts) => { let I_MockRedemptionManagerFactory; let I_MockRedemptionManager; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -104,6 +112,10 @@ contract("SecurityToken", async (accounts) => { let currentTime; + async function readStorage(contractAddress, slot) { + return await web3.eth.getStorageAt(contractAddress, slot); + } + before(async () => { currentTime = new BN(await latestTime()); account_polymath = accounts[0]; @@ -135,7 +147,8 @@ contract("SecurityToken", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -178,23 +191,22 @@ contract("SecurityToken", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // 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]; + let moduleData = (await stGetter.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = await 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 () => { + it("Should issue the tokens before attaching the STO -- fail only be called by the owner", async () => { currentTime = new BN(await latestTime()); let toTime = new BN(currentTime.add(new BN(duration.days(100)))); let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); @@ -204,16 +216,16 @@ contract("SecurityToken", async (accounts) => { gas: 6000000 }); assert.equal(tx.logs[0].args._investor, account_affiliate1, "Failed in adding the investor in whitelist"); - await catchRevert(I_SecurityToken.mint(account_investor1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: account_delegate })); + await catchRevert(I_SecurityToken.issue(account_investor1, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: account_delegate })); }); - it("Should mint the tokens before attaching the STO", async () => { - await I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner }); + it("Should issue the tokens before attaching the STO", async () => { + await I_SecurityToken.issue(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner }); let balance = await I_SecurityToken.balanceOf(account_affiliate1); assert.equal(balance.div(new BN(10).pow(new BN(18))).toNumber(), 100); }); - it("Should mint the multi tokens before attaching the STO -- fail only be called by the owner", async () => { + it("Should issue the multi tokens before attaching the STO -- fail only be called by the owner", async () => { currentTime = new BN(await latestTime()); let toTime = new BN(currentTime.add(new BN(duration.days(100)))); let expiryTime = new BN(toTime.add(new BN(duration.days(100)))); @@ -225,59 +237,83 @@ contract("SecurityToken", async (accounts) => { assert.equal(tx.logs[0].args._investor, account_affiliate2, "Failed in adding the investor in whitelist"); await catchRevert( - I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { + I_SecurityToken.issueMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { from: account_delegate, gas: 500000 }) ); }); - it("Should mintMulti", async () => { + it("Should check the balance of the locked tokens", async() => { + console.log(`\t Total balance: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_affiliate1)).toString())}`); + console.log(`\t Locked balance: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_affiliate1, web3.utils.utf8ToHex(`LOCKED`))).toString())}`); + console.log(`\t Unlocked balance: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_affiliate1, web3.utils.utf8ToHex(`UNLOCKED`))).toString())}`); + assert.equal( + web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_affiliate1, web3.utils.utf8ToHex(`LOCKED`))).toString()), + 0 + ); + assert.equal( + web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_affiliate1, web3.utils.utf8ToHex(`UNLOCKED`))).toString()), + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_affiliate1)).toString()) + ); + console.log(`\t Wrong partition: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_affiliate1, web3.utils.toHex(`OCKED`))).toString())}`); + assert.equal( + web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_affiliate1, web3.utils.toHex(`OCKED`))).toString()), + 0 + ); + }); + + + it("Should issueMulti", async () => { await catchRevert( - I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18)))], { + I_SecurityToken.issueMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18)))], { from: token_owner, gas: 500000 }) ); }); - it("Should mint the tokens for multiple afiliated investors before attaching the STO", async () => { - await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { + it("Should issue the tokens for multiple afiliated investors before attaching the STO", async () => { + await I_SecurityToken.issueMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { from: token_owner }); let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); assert.equal(balance1.div(new BN(10).pow(new BN(18))).toNumber(), 200); let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); assert.equal(balance2.div(new BN(10).pow(new BN(18))).toNumber(), 110); + }); + it("Should ST be issuable", async() => { + assert.isTrue(await I_SecurityToken.isIssuable.call()); + }) + it("Should finish the minting -- fail because feature is not activated", async () => { - await catchRevert(I_SecurityToken.freezeMinting({ from: token_owner })); + await catchRevert(I_SecurityToken.freezeIssuance({ from: token_owner })); }); it("Should finish the minting -- fail to activate the feature because msg.sender is not polymath", async () => { - await catchRevert(I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, { from: token_owner })); + await catchRevert(I_FeatureRegistry.setFeatureStatus("freezeIssuanceAllowed", true, { from: token_owner })); }); it("Should finish the minting -- successfully activate the feature", async () => { - await catchRevert(I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", false, { from: account_polymath })); + await catchRevert(I_FeatureRegistry.setFeatureStatus("freezeIssuanceAllowed", false, { from: account_polymath })); + assert.equal(false, await I_FeatureRegistry.getFeatureStatus("freezeIssuanceAllowed", { from: account_temp })); + await I_FeatureRegistry.setFeatureStatus("freezeIssuanceAllowed", true, { from: account_polymath }); + assert.equal(true, await I_FeatureRegistry.getFeatureStatus("freezeIssuanceAllowed", { from: account_temp })); - 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 })); - - await catchRevert(I_FeatureRegistry.setFeatureStatus("freezeMintingAllowed", true, { from: account_polymath })); + await catchRevert(I_FeatureRegistry.setFeatureStatus("freezeIssuanceAllowed", true, { from: account_polymath })); }); it("Should finish the minting -- fail because msg.sender is not the owner", async () => { - await catchRevert(I_SecurityToken.freezeMinting({ from: account_temp })); + await catchRevert(I_SecurityToken.freezeIssuance({ from: account_temp })); }); it("Should finish minting & restrict the further minting", async () => { let id = await takeSnapshot(); - await I_SecurityToken.freezeMinting({ from: token_owner }); - - await catchRevert(I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner, gas: 500000 })); + await I_SecurityToken.freezeIssuance({ from: token_owner }); + assert.isFalse(await I_SecurityToken.isIssuable.call()); + await catchRevert(I_SecurityToken.issue(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner, gas: 500000 })); await revertToSnapshot(id); }); @@ -285,7 +321,6 @@ contract("SecurityToken", async (accounts) => { startTime = await latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - await catchRevert(I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), { from: token_owner })); }); @@ -313,7 +348,6 @@ contract("SecurityToken", async (accounts) => { const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, new BN(0), web3.utils.fromAscii("stofactory"), { from: token_owner }); - console.log("1"); 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"); console.log("module label is .. " + web3.utils.toAscii(tx.logs[3].args._label)); @@ -337,24 +371,25 @@ contract("SecurityToken", async (accounts) => { I_CappedSTO = await CappedSTO.at(tx.logs[3].args._module); }); - it("Should successfully mint tokens while STO attached", async () => { - await I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner }); + it("Should successfully issue tokens while STO attached", async () => { + await I_SecurityToken.issue(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner }); + let balance = await I_SecurityToken.balanceOf(account_affiliate1); assert.equal(balance.div(new BN(10).pow(new BN(18))).toNumber(), 300); }); - it("Should fail to mint tokens while STO attached after freezeMinting called", async () => { + it("Should fail to issue tokens while STO attached after freezeMinting called", async () => { let id = await takeSnapshot(); - await I_SecurityToken.freezeMinting({ from: token_owner }); + await I_SecurityToken.freezeIssuance({ from: token_owner }); - await catchRevert(I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner })); + await catchRevert(I_SecurityToken.issue(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner })); await revertToSnapshot(id); }); }); describe("Module related functions", async () => { it(" Should get the modules of the securityToken by name", async () => { - let moduleData = await I_SecurityToken.getModule.call(I_CappedSTO.address); + let moduleData = await stGetter.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); @@ -364,26 +399,26 @@ contract("SecurityToken", async (accounts) => { }); 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); + let moduleData = await stGetter.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(web3.utils.fromAscii("CappedSTO")); + let moduleList = await stGetter.getModulesByName.call(web3.utils.fromAscii("CappedSTO")); assert.isTrue(moduleList.length == 1, "Only one STO"); - let moduleData = await I_SecurityToken.getModule.call(moduleList[0]); + let moduleData = await stGetter.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(web3.utils.fromAscii("GeneralPermissionManager")); + let moduleData = await stGetter.getModulesByName.call(web3.utils.fromAscii("GeneralPermissionManager")); assert.isTrue(moduleData.length == new BN(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(web3.utils.fromAscii("CountTransferManager")); + let moduleData = await stGetter.getModulesByName.call(web3.utils.fromAscii("CountTransferManager")); assert.isTrue(moduleData.length == new BN(0), "No Permission Manager"); }); @@ -414,8 +449,15 @@ contract("SecurityToken", async (accounts) => { 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 I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("500")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("500")), "0x0", { from: token_owner }); + let _canTransfer = await I_SecurityToken.canTransfer.call(account_investor2, new BN(web3.utils.toWei("200")), "0x0", {from: account_investor1}); + + assert.isTrue(_canTransfer[0]); + assert.equal(_canTransfer[1], 0x51); + assert.equal(_canTransfer[2], empty_hash); + await I_SecurityToken.transfer(account_investor2, new BN(web3.utils.toWei("200")), { from: account_investor1 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).div(new BN(10).pow(new BN(18))).toNumber(), 200); await revertToSnapshot(key); }); @@ -453,7 +495,7 @@ contract("SecurityToken", async (accounts) => { }); it("Should verify the revertion of snapshot works properly", async () => { - let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); + let moduleData = await stGetter.getModule.call(I_GeneralTransferManager.address); assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ""), "GeneralTransferManager"); assert.equal(moduleData[1], I_GeneralTransferManager.address); }); @@ -462,16 +504,16 @@ contract("SecurityToken", async (accounts) => { 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); + let moduleData = await stGetter.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 () => { + it("Should successfully issue tokens while GTM archived", async () => { let key = await takeSnapshot(); - await I_SecurityToken.mint(one_address, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner, gas: 500000 }); + await I_SecurityToken.issue(one_address, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner, gas: 500000 }); let balance = await I_SecurityToken.balanceOf(one_address); assert.equal(balance.div(new BN(10).pow(new BN(18))).toNumber(), 100); await revertToSnapshot(key); @@ -481,7 +523,7 @@ contract("SecurityToken", async (accounts) => { 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); + let moduleData = await stGetter.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); @@ -496,8 +538,8 @@ contract("SecurityToken", async (accounts) => { await catchRevert(I_SecurityToken.archiveModule(I_GeneralPermissionManagerFactory.address, { from: token_owner })); }); - it("Should fail to mint tokens while GTM unarchived", async () => { - await catchRevert(I_SecurityToken.mint(one_address, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner, gas: 500000 })); + it("Should fail to issue tokens while GTM unarchived", async () => { + await catchRevert(I_SecurityToken.issue(one_address, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner, gas: 500000 })); }); it("Should change the budget of the module - fail incorrect address", async () => { @@ -523,7 +565,7 @@ contract("SecurityToken", async (accounts) => { }); it("Should fail to get the total supply -- because checkpoint id is greater than present", async () => { - await catchRevert(I_SecurityToken.totalSupplyAt.call(50)); + await catchRevert(stGetter.totalSupplyAt.call(50)); }); }); @@ -560,13 +602,18 @@ contract("SecurityToken", async (accounts) => { }); it("Should Fail in transferring the token from one whitelist investor 1 to non whitelist investor 2", async () => { + let _canTransfer = await I_SecurityToken.canTransfer.call(account_investor2, new BN(10).mul(new BN(10).pow(new BN(18))), "0x0", {from: account_investor1}); + + assert.isFalse(_canTransfer[0]); + assert.equal(_canTransfer[1], 0x50); + await catchRevert(I_SecurityToken.transfer(account_investor2, new BN(10).mul(new BN(10).pow(new BN(18))), { from: account_investor1 })); }); it("Should fail to provide the permission to the delegate to change the transfer bools -- Bad owner", async () => { // Add permission to the deletgate (A regesteration process) await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(0), { from: token_owner }); - let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; + let moduleData = (await stGetter.getModulesByType(permissionManagerKey))[0]; I_GeneralPermissionManager = await GeneralPermissionManager.at(moduleData); await catchRevert(I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_temp })); }); @@ -584,7 +631,6 @@ contract("SecurityToken", async (accounts) => { 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"); }); @@ -687,20 +733,21 @@ contract("SecurityToken", async (accounts) => { await revertToSnapshot(ID_snap); }); - it("Should successfully mint tokens while STO attached", async () => { - await I_SecurityToken.mint(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), { from: token_owner }); + it("Should successfully issue tokens while STO attached", async () => { + await I_SecurityToken.issue(account_affiliate1, new BN(100).mul(new BN(10).pow(new BN(18))), "0x0", { from: token_owner }); let balance = await I_SecurityToken.balanceOf(account_affiliate1); assert.equal(balance.div(new BN(10).pow(new BN(18))).toNumber(), 400); }); - it("Should mint the tokens for multiple afiliated investors while STO attached", async () => { - await I_SecurityToken.mintMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { + it("Should issue the tokens for multiple afiliated investors while STO attached", async () => { + await I_SecurityToken.issueMulti([account_affiliate1, account_affiliate2], [new BN(100).mul(new BN(10).pow(new BN(18))), new BN(110).mul(new BN(10).pow(new BN(18)))], { from: token_owner }); let balance1 = await I_SecurityToken.balanceOf(account_affiliate1); assert.equal(balance1.div(new BN(10).pow(new BN(18))).toNumber(), 500); let balance2 = await I_SecurityToken.balanceOf(account_affiliate2); assert.equal(balance2.div(new BN(10).pow(new BN(18))).toNumber(), 220); + }); it("Should provide more permissions to the delegate", async () => { @@ -739,9 +786,9 @@ contract("SecurityToken", async (accounts) => { assert.equal((await I_SecurityToken.balanceOf(account_investor1)).div(new BN(10).pow(new BN(18))).toNumber(), 1000); }); - it("STO should fail to mint tokens after minting is frozen", async () => { + it("STO should fail to issue tokens after minting is frozen", async () => { let id = await takeSnapshot(); - await I_SecurityToken.freezeMinting({ from: token_owner }); + await I_SecurityToken.freezeIssuance({ from: token_owner }); await catchRevert( web3.eth.sendTransaction({ @@ -824,7 +871,7 @@ contract("SecurityToken", async (accounts) => { 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 investors = await stGetter.getInvestors.call(); let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; for (let i = 0; i < expectedAccounts.length; i++) { assert.equal(investors[i], expectedAccounts[i]); @@ -861,11 +908,15 @@ contract("SecurityToken", async (accounts) => { assert.equal(account_controller, controller, "Status not set correctly"); }); + it("Should ST be the controllable", async() => { + assert.isTrue(await I_SecurityToken.isControllable.call()); + }); + it("Should force burn the tokens - value too high", async () => { await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, { from: token_owner }); let currentBalance = await I_SecurityToken.balanceOf(account_temp); await catchRevert( - I_SecurityToken.forceBurn(account_temp, currentBalance + new BN(web3.utils.toWei("500", "ether")), "0x0", "0x0", { + I_SecurityToken.controllerRedeem(account_temp, currentBalance + new BN(web3.utils.toWei("500", "ether")), "0x0", "0x0", { from: account_controller }) ); @@ -873,14 +924,19 @@ contract("SecurityToken", async (accounts) => { it("Should force burn the tokens - wrong caller", async () => { await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, { from: token_owner }); let currentBalance = await I_SecurityToken.balanceOf(account_temp); - await catchRevert(I_SecurityToken.forceBurn(account_temp, currentBalance, "0x0", "0x0", { from: token_owner })); + let investors = await stGetter.getInvestors.call(); + for (let i = 0; i < investors.length; i++) { + console.log(investors[i]); + console.log(web3.utils.fromWei((await I_SecurityToken.balanceOf(investors[i])).toString())); + } + await catchRevert(I_SecurityToken.controllerRedeem(account_temp, currentBalance, "0x0", "0x0", { from: token_owner })); }); it("Should burn the tokens", async () => { let currentInvestorCount = await I_SecurityToken.holderCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); - // console.log(currentInvestorCount.toString(), currentBalance.toString()); - let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "0x0", "0x0", { from: account_controller }); + let investors = await stGetter.getInvestors.call(); + let tx = await I_SecurityToken.controllerRedeem(account_temp, currentBalance, "0x0", "0x0", { from: account_controller }); // console.log(tx.logs[1].args._value.toNumber(), currentBalance.toNumber()); assert.equal(tx.logs[1].args._value.toString(), currentBalance.toString()); let newInvestorCount = await I_SecurityToken.holderCount.call(); @@ -890,7 +946,7 @@ contract("SecurityToken", async (accounts) => { it("Should use getInvestorsAt to determine balances now", async () => { await I_SecurityToken.createCheckpoint({ from: token_owner }); - let investors = await I_SecurityToken.getInvestorsAt.call(1); + let investors = await stGetter.getInvestorsAt.call(1); console.log("Filtered investors:" + investors); let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; for (let i = 0; i < expectedAccounts.length; i++) { @@ -905,14 +961,14 @@ contract("SecurityToken", async (accounts) => { 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(); + let investors = await stGetter.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); + investors = await stGetter.getInvestorsAt.call(2); console.log("Filtered investors:" + investors); expectedAccounts = [account_affiliate1]; for (let i = 0; i < expectedAccounts.length; i++) { @@ -924,33 +980,33 @@ contract("SecurityToken", async (accounts) => { }); it("Should get filtered investors", async () => { - let investors = await I_SecurityToken.getInvestors.call(); + let investors = await stGetter.getInvestors.call(); console.log("All Investors: " + investors); - let filteredInvestors = await I_SecurityToken.iterateInvestors.call(0, 0); + let filteredInvestors = await stGetter.iterateInvestors.call(0, 0); console.log("Filtered Investors (0, 0): " + filteredInvestors); assert.equal(filteredInvestors[0], investors[0]); assert.equal(filteredInvestors.length, 1); - filteredInvestors = await I_SecurityToken.iterateInvestors.call(2, 3); + filteredInvestors = await stGetter.iterateInvestors.call(2, 3); console.log("Filtered Investors (2, 3): " + 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, 3); + filteredInvestors = await stGetter.iterateInvestors.call(0, 3); console.log("Filtered Investors (0, 3): " + 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)); + await catchRevert(stGetter.iterateInvestors(0, 5)); }); it("Should check the balance of investor at checkpoint", async () => { - await catchRevert(I_SecurityToken.balanceOfAt(account_investor1, 5)); + await catchRevert(stGetter.balanceOfAt(account_investor1, 5)); }); it("Should check the balance of investor at checkpoint", async () => { - let balance = await I_SecurityToken.balanceOfAt(account_investor1, 0); + let balance = await stGetter.balanceOfAt(account_investor1, 0); assert.equal(balance.toNumber(), 0); }); }); @@ -979,7 +1035,7 @@ contract("SecurityToken", async (accounts) => { it("Should successfully burn tokens", async () => { await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(false, { from: token_owner }); // Minting some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1000")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1000")), "0x0", { from: token_owner }); // Provide approval to trnafer the tokens to Module await I_SecurityToken.approve(I_MockRedemptionManager.address, new BN(web3.utils.toWei("500")), { from: account_investor1 }); // Allow all whitelist transfer @@ -994,6 +1050,7 @@ contract("SecurityToken", async (accounts) => { it("Should fail to burn the tokens because module get archived", async () => { await I_SecurityToken.archiveModule(I_MockRedemptionManager.address, { from: token_owner }); + console.log(await stGetter.getModule.call(I_MockRedemptionManager.address)); await catchRevert(I_MockRedemptionManager.redeemTokenByOwner(new BN(web3.utils.toWei("250")), { from: account_investor1 })); }); @@ -1061,31 +1118,31 @@ contract("SecurityToken", async (accounts) => { }); describe("Force Transfer", async () => { - it("Should fail to forceTransfer because not approved controller", async () => { + it("Should fail to controllerTransfer because not approved controller", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { + I_SecurityToken.controllerTransfer(account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_investor1 }) ); }); - it("Should fail to forceTransfer because insufficient balance", async () => { + it("Should fail to controllerTransfer because insufficient balance", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor2, account_investor1, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { + I_SecurityToken.controllerTransfer(account_investor2, account_investor1, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_controller }) ); }); - it("Should fail to forceTransfer because recipient is zero address", async () => { + it("Should fail to controllerTransfer because recipient is zero address", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor1, address_zero, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { + I_SecurityToken.controllerTransfer(account_investor1, address_zero, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_controller }) ); }); - it("Should successfully forceTransfer", async () => { + it("Should successfully controllerTransfer", async () => { let sender = account_investor1; let receiver = account_investor2; @@ -1093,7 +1150,7 @@ contract("SecurityToken", async (accounts) => { 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( + let tx = await I_SecurityToken.controllerTransfer( account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), @@ -1119,16 +1176,11 @@ contract("SecurityToken", async (accounts) => { ); let eventForceTransfer = tx.logs[1]; let eventTransfer = tx.logs[0]; - console.log(eventForceTransfer.args); - console.log(eventTransfer.args); assert.equal(account_controller, eventForceTransfer.args._controller, "Event not emitted as expected"); assert.equal(account_investor1, eventForceTransfer.args._from, "Event not emitted as expected"); assert.equal(account_investor2, eventForceTransfer.args._to, "Event not emitted as expected"); assert.equal(new BN(web3.utils.toWei("10", "ether")).toString(), eventForceTransfer.args._value.toString(), "Event not emitted as expected"); - console.log(eventForceTransfer.args._verifyTransfer); - assert.equal(false, eventForceTransfer.args._verifyTransfer, "Event not emitted as expected"); - assert.equal("reason", web3.utils.hexToUtf8(eventForceTransfer.args._data), "Event not emitted as expected"); - + assert.equal("reason", web3.utils.hexToUtf8(eventForceTransfer.args._operatorData), "Event not emitted as expected"); assert.equal(account_investor1, eventTransfer.args.from, "Event not emitted as expected"); assert.equal(account_investor2, eventTransfer.args.to, "Event not emitted as expected"); assert.equal(new BN(web3.utils.toWei("10", "ether")).toString(), eventTransfer.args.value.toString(), "Event not emitted as expected"); @@ -1156,6 +1208,10 @@ contract("SecurityToken", async (accounts) => { assert.equal(true, await I_SecurityToken.controllerDisabled.call(), "State not changed"); }); + it("Should ST be not controllable", async() => { + assert.isFalse(await I_SecurityToken.isControllable.call()); + }); + it("Should fail to freeze controller functionality because already frozen", async () => { await catchRevert(I_SecurityToken.disableController({ from: token_owner })); }); @@ -1164,12 +1220,357 @@ contract("SecurityToken", async (accounts) => { await catchRevert(I_SecurityToken.setController(account_controller, { from: token_owner })); }); - it("Should fail to forceTransfer because controller functionality frozen", async () => { + it("Should fail to controllerTransfer because controller functionality frozen", async () => { await catchRevert( - I_SecurityToken.forceTransfer(account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { + I_SecurityToken.controllerTransfer(account_investor1, account_investor2, new BN(web3.utils.toWei("10", "ether")), "0x0", web3.utils.fromAscii("reason"), { from: account_controller }) ); }); + + }); + + describe("Test cases for the storage", async() => { + + it("Test the storage values of the ERC20 vairables", async() => { + let investors = await stGetter.getInvestors.call(); + + console.log("Verifying the balances of the Addresses"); + let index; + let key; + let newKey = new Array(); + + function encodeUint(data) { + return web3.eth.abi.encodeParameter('uint256', data); + } + + for (let i = 0; i < investors.length; i++) { + index = encodeUint(0); + key = web3.eth.abi.encodeParameter('address', investors[i]) + var tempKey = key + index.substring(2); + newKey.push(encodeUint(web3.utils.sha3(tempKey, {"encoding": "hex"}))); + } + + assert.equal( + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[0])).toString()), + web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[0]))).toString()) + ) + console.log(` + Balances from the contract: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[0])).toString())} + Balances from the storage: ${web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[0]))).toString())} + `) + + assert.equal( + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[1])).toString()), + web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[1]))).toString()) + ); + console.log(` + Balances from the contract: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[1])).toString())} + Balances from the storage: ${web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[1]))).toString())} + `) + + assert.equal( + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[2])).toString()), + web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[2]))).toString()) + ); + console.log(` + Balances from the contract: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[2])).toString())} + Balances from the storage: ${web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[2]))).toString())} + `) + assert.equal( + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[3])).toString()), + web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[3]))).toString()) + ) + console.log(` + Balances from the contract: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(investors[3])).toString())} + Balances from the storage: ${web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, newKey[3]))).toString())} + `) + assert.equal( + web3.utils.fromWei((await I_SecurityToken.totalSupply.call()).toString()), + web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, 2))).toString()) + ); + console.log(` + TotalSupply from contract: ${web3.utils.fromWei((await I_SecurityToken.totalSupply.call()).toString())} + TotalSupply from the storage: ${web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, 2))).toString())} + `); + assert.equal( + await I_SecurityToken.name.call(), + (web3.utils.toAscii(await readStorage(I_SecurityToken.address, 3)).replace(/\u0000/g, "")).replace(/\u0014/g, "") + ) + console.log(` + Name of the ST: ${await I_SecurityToken.name.call()} + Name of the ST from the storage: ${web3.utils.toUtf8(await readStorage(I_SecurityToken.address, 3))} + `); + assert.equal( + await I_SecurityToken.symbol.call(), + (web3.utils.toUtf8(await readStorage(I_SecurityToken.address, 4)).replace(/\u0000/g, "")).replace(/\u0006/g, "") + ); + console.log(` + Symbol of the ST: ${await I_SecurityToken.symbol.call()} + Symbol of the ST from the storage: ${web3.utils.toUtf8(await readStorage(I_SecurityToken.address, 4))} + `); + + console.log(` + Address of the owner: ${await I_SecurityToken.owner.call()} + Address of the owner from the storage: ${(await readStorage(I_SecurityToken.address, 5)).substring(0, 42)} + `) + assert.equal( + await I_SecurityToken.owner.call(), + web3.utils.toChecksumAddress((await readStorage(I_SecurityToken.address, 5)).substring(0, 42)) + ); + + }); + + it("Verify the storage of the STStorage", async() => { + // for (let j = 7; j < 35; j++) { + // console.log(await readStorage(I_SecurityToken.address, j)); + // } + + console.log(` + Controller address from the contract: ${await stGetter.controller.call()} + Controller address from the storage: ${await readStorage(I_SecurityToken.address, 7)} + `) + + assert.equal( + (await stGetter.controller.call()).substring(0, 3), + await readStorage(I_SecurityToken.address, 7) + ); + + console.log(` + PolymathRegistry address from the contract: ${await stGetter.polymathRegistry.call()} + PolymathRegistry address from the storage: ${await readStorage(I_SecurityToken.address, 8)} + `) + + assert.equal( + await stGetter.polymathRegistry.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 8)) + ); + console.log(` + ModuleRegistry address from the contract: ${await stGetter.moduleRegistry.call()} + ModuleRegistry address from the storage: ${await readStorage(I_SecurityToken.address, 9)} + `) + + assert.equal( + await stGetter.moduleRegistry.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 9)) + ); + + console.log(` + SecurityTokenRegistry address from the contract: ${await stGetter.securityTokenRegistry.call()} + SecurityTokenRegistry address from the storage: ${await readStorage(I_SecurityToken.address, 10)} + `) + + assert.equal( + await stGetter.securityTokenRegistry.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 10)) + ); + + console.log(` + FeatureRegistry address from the contract: ${await stGetter.featureRegistry.call()} + FeatureRegistry address from the storage: ${await readStorage(I_SecurityToken.address, 11)} + `) + + assert.equal( + await stGetter.featureRegistry.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 11)) + ); + + console.log(` + PolyToken address from the contract: ${await stGetter.polyToken.call()} + PolyToken address from the storage: ${await readStorage(I_SecurityToken.address, 12)} + `) + + assert.equal( + await stGetter.polyToken.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 12)) + ); + + console.log(` + Delegate address from the contract: ${await stGetter.delegate.call()} + Delegate address from the storage: ${await readStorage(I_SecurityToken.address, 13)} + `) + + assert.equal( + await stGetter.delegate.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 13)) + ); + + console.log(` + Datastore address from the contract: ${await stGetter.dataStore.call()} + Datastore address from the storage: ${await readStorage(I_SecurityToken.address, 14)} + `) + + assert.equal( + await stGetter.dataStore.call(), + web3.utils.toChecksumAddress(await readStorage(I_SecurityToken.address, 14)) + ); + + console.log(` + Granularity value from the contract: ${await stGetter.granularity.call()} + Granularity value from the storage: ${(web3.utils.toBN(await readStorage(I_SecurityToken.address, 15))).toString()} + `) + + assert.equal( + web3.utils.fromWei(await stGetter.granularity.call()), + web3.utils.fromWei((web3.utils.toBN(await readStorage(I_SecurityToken.address, 15))).toString()) + ); + + console.log(` + Current checkpoint ID from the contract: ${await stGetter.currentCheckpointId.call()} + Current checkpoint ID from the storage: ${(web3.utils.toBN(await readStorage(I_SecurityToken.address, 16))).toString()} + `) + assert.equal( + await stGetter.currentCheckpointId.call(), + (web3.utils.toBN(await readStorage(I_SecurityToken.address, 16))).toString() + ); + + console.log(` + TokenDetails from the contract: ${await stGetter.tokenDetails.call()} + TokenDetails from the storage: ${(web3.utils.toUtf8((await readStorage(I_SecurityToken.address, 17)).substring(0, 60)))} + `) + assert.equal( + await stGetter.tokenDetails.call(), + (web3.utils.toUtf8((await readStorage(I_SecurityToken.address, 17)).substring(0, 60))).replace(/\u0000/g, "") + ); + + }); + }); + + describe(`Test cases for the ERC1643 contract\n`, async () => { + + describe(`Test cases for the setDocument() function of the ERC1643\n`, async() => { + + it("\tShould failed in executing the setDocument() function because msg.sender is not authorised\n", async() => { + await catchRevert( + I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc1"), "https://www.gogl.bts.fly", "0x0", {from: account_temp}) + ); + }); + + it("\tShould failed to set a document details as name is empty\n", async() => { + await catchRevert( + I_SecurityToken.setDocument(web3.utils.utf8ToHex(""), "https://www.gogl.bts.fly", "0x0", {from: token_owner}) + ); + }); + + it("\tShould failed to set a document details as URI is empty\n", async() => { + await catchRevert( + I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc1"), "", "0x0", {from: token_owner}) + ); + }); + + it("\tShould sucessfully add the document details in the `_documents` mapping and change the length of the `_docsNames`\n", async() => { + let tx = await I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc1"), uri, docHash, {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._name), "doc1"); + assert.equal(tx.logs[0].args._uri, uri); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._documentHash), web3.utils.toUtf8(docHash)); + assert.equal((await stGetter.getAllDocuments.call()).length, 1); + }); + + it("\tShould successfully add the new document and allow the empty docHash to be added in the `Document` structure\n", async() => { + let tx = await I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc2"), uri, "0x0", {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._name), "doc2"); + assert.equal(tx.logs[0].args._uri, uri); + assert.equal(tx.logs[0].args._documentHash, empty_hash); + assert.equal((await stGetter.getAllDocuments.call()).length, 2); + }); + + it("\tShould successfully update the existing document and length of `_docsNames` should remain unaffected\n", async() => { + let tx = await I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc2"), "https://www.bts.l", "0x0", {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._name), "doc2"); + assert.equal(tx.logs[0].args._uri, "https://www.bts.l"); + assert.equal(tx.logs[0].args._documentHash, empty_hash); + assert.equal((await stGetter.getAllDocuments.call()).length, 2); + }); + + describe("Test cases for the getters functions\n", async()=> { + + it("\tShould get the details of existed document\n", async() => { + let doc1Details = await stGetter.getDocument.call(web3.utils.utf8ToHex("doc1")); + assert.equal(doc1Details[0], uri); + assert.equal(web3.utils.toUtf8(doc1Details[1]), web3.utils.toUtf8(docHash)); + assert.closeTo(doc1Details[2].toNumber(), await latestTime(), 2); + + let doc2Details = await stGetter.getDocument.call(web3.utils.utf8ToHex("doc2")); + assert.equal(doc2Details[0], "https://www.bts.l"); + assert.equal(doc2Details[1], empty_hash); + assert.closeTo(doc2Details[2].toNumber(), await latestTime(), 2); + }); + + it("\tShould get the details of the non-existed document it means every value should be zero\n", async() => { + let doc3Details = await stGetter.getDocument.call(web3.utils.utf8ToHex("doc3")); + assert.equal(doc3Details[0], ""); + assert.equal(web3.utils.toUtf8(doc3Details[1]), ""); + assert.equal(doc3Details[2], 0); + }); + + it("\tShould get all the documents present in the contract\n", async() => { + let allDocs = await stGetter.getAllDocuments.call() + assert.equal(allDocs.length, 2); + assert.equal(web3.utils.toUtf8(allDocs[0]), "doc1"); + assert.equal(web3.utils.toUtf8(allDocs[1]), "doc2"); + }); + }) + }); + + describe("Test cases for the removeDocument()\n", async() => { + + it("\tShould failed to remove document because msg.sender is not authorised\n", async() => { + await catchRevert( + I_SecurityToken.removeDocument(web3.utils.utf8ToHex("doc2"), {from: account_temp}) + ); + }); + + it("\tShould failed to remove the document that is not existed in the contract\n", async() => { + await catchRevert( + I_SecurityToken.removeDocument(web3.utils.utf8ToHex("doc3"), {from: token_owner}) + ); + }); + + it("\tShould succssfully remove the document from the contract which is present in the last index of the `_docsName` and check the params of the `DocumentRemoved` event\n", async() => { + // first add the new document + await I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc3"), "https://www.bts.l", "0x0", {from: token_owner}); + // as this will be last in the array so remove this + let tx = await I_SecurityToken.removeDocument(web3.utils.utf8ToHex("doc3"), {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._name), "doc3"); + assert.equal(tx.logs[0].args._uri, "https://www.bts.l"); + assert.equal(tx.logs[0].args._documentHash, empty_hash); + assert.equal((await stGetter.getAllDocuments.call()).length, 2); + + // remove the document that is not last in the `docsName` array + tx = await I_SecurityToken.removeDocument(web3.utils.utf8ToHex("doc1"), {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._name), "doc1"); + assert.equal(tx.logs[0].args._uri, uri); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._documentHash), web3.utils.toUtf8(docHash)); + assert.equal((await stGetter.getAllDocuments.call()).length, 1); + }); + + it("\t Should delete the doc to validate the #17 issue problem", async() => { + let tx = await I_SecurityToken.removeDocument(web3.utils.utf8ToHex("doc2"), {from: token_owner}); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._name), "doc2"); + assert.equal(tx.logs[0].args._uri, "https://www.bts.l"); + assert.equal(web3.utils.toUtf8(tx.logs[0].args._documentHash), ''); + assert.equal((await stGetter.getAllDocuments.call()).length, 0); + }); + + describe("Test cases for the getters functions\n", async()=> { + + it("\tShould get the details of the non-existed (earlier was present but get removed ) document it means every value should be zero\n", async() => { + let doc1Details = await stGetter.getDocument.call(web3.utils.utf8ToHex("doc1")); + assert.equal(doc1Details[0], ""); + assert.equal(web3.utils.toUtf8(doc1Details[1]), ""); + assert.equal(doc1Details[2], 0); + }); + + it("\tShould get all the documents present in the contract which should be 1\n", async() => { + // add one doc before the getter call + await I_SecurityToken.setDocument(web3.utils.utf8ToHex("doc4"), "https://www.bts.l", docHash, {from: token_owner}) + let allDocs = await stGetter.getAllDocuments.call() + assert.equal(allDocs.length, 1); + assert.equal(web3.utils.toUtf8(allDocs[0]), "doc4"); + }); + }); + }) + }); + }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 4e3983966..0aea11023 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -10,6 +10,7 @@ const MockOracle = artifacts.require("./MockOracle.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -62,6 +63,8 @@ contract("USDTieredSTO", async (accounts) => { let I_PolymathRegistry; let P_USDTieredSTOFactory; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details for funds raise Type ETH const NAME = "Team"; @@ -233,7 +236,9 @@ contract("USDTieredSTO", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter, + I_STGetter ] = instances; I_DaiToken = await PolyTokenFaucet.new({from: POLYMATH}); @@ -285,7 +290,7 @@ contract("USDTieredSTO", async (accounts) => { assert.equal(tx.logs[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -294,7 +299,7 @@ contract("USDTieredSTO", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; + let moduleData = (await stGetter.getModulesByType(TMKEY))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 30e72d055..1bed3ccb7 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -12,6 +12,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -58,6 +59,8 @@ contract("USDTieredSTO Sim", async (accounts) => { let I_DaiToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details for funds raise Type ETH const NAME = "Team"; @@ -210,7 +213,8 @@ contract("USDTieredSTO Sim", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; I_DaiToken = await PolyTokenFaucet.new({ from: POLYMATH }); @@ -261,7 +265,7 @@ contract("USDTieredSTO Sim", async (accounts) => { assert.equal(tx.logs[2].args._ticker, SYMBOL, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -270,7 +274,7 @@ contract("USDTieredSTO Sim", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; + let moduleData = (await stGetter.getModulesByType(TMKEY))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index e36207717..c8bf6c781 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -15,6 +15,7 @@ const DummySTO = artifacts.require("./DummySTO.sol"); const PreSaleSTO = artifacts.require("./PreSaleSTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -45,6 +46,8 @@ contract("Concurrent STO", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // STO instance declaration let I_CappedSTOFactory; @@ -98,7 +101,8 @@ contract("Concurrent STO", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the STO Factories @@ -148,7 +152,7 @@ contract("Concurrent STO", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol, "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -157,7 +161,7 @@ contract("Concurrent STO", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; + let moduleData = (await stGetter.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index d2767dedd..bae86e140 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -10,6 +10,7 @@ const OwnedUpgradeabilityProxy = artifacts.require("./OwnedUpgradeabilityProxy.s const STFactory = artifacts.require("./STFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const STRGetter = artifacts.require("./STRGetter.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -31,6 +32,8 @@ contract("SecurityTokenRegistryProxy", async (accounts) => { let I_FeatureRegistry; let I_STRGetter; let I_Getter; + let I_STGetter; + let stGetter; let account_polymath; let account_temp; @@ -80,7 +83,8 @@ contract("SecurityTokenRegistryProxy", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({ from: account_polymath }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index c4d3c2d98..1dc2b8f18 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -13,6 +13,7 @@ const GeneralTransferManagerLogic = artifacts.require("./GeneralTransferManager. const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const DataStoreLogic = artifacts.require('./DataStore.sol'); const DataStoreFactory = artifacts.require('./DataStoreFactory.sol'); @@ -37,6 +38,8 @@ contract("ModuleRegistryProxy", async (accounts) => { let I_ModuleRegistry; let I_FeatureRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; let account_polymath; let account_temp; @@ -82,7 +85,8 @@ contract("ModuleRegistryProxy", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: account_polymath}); @@ -152,9 +156,10 @@ contract("ModuleRegistryProxy", async (accounts) => { await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // Step 3: Deploy the STFactory contract + I_STGetter = await STGetter.new(); let I_DataStoreLogic = await DataStoreLogic.new({ from: account_polymath }); let I_DataStoreFactory = await DataStoreFactory.new(I_DataStoreLogic.address, { from: account_polymath }); - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, { from: account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, I_DataStoreFactory.address, I_STGetter.address, { from: account_polymath }); assert.notEqual(I_STFactory.address.valueOf(), address_zero, "STFactory contract was not deployed"); }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index dd22c1c51..da8a29531 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -8,6 +8,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const TrackedRedemption = artifacts.require("./TrackedRedemption"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -47,6 +48,8 @@ contract("TrackedRedemption", async (accounts) => { let I_PolymathRegistry; let P_TrackedRedemptionFactory; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -99,7 +102,8 @@ contract("TrackedRedemption", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; @@ -142,7 +146,7 @@ contract("TrackedRedemption", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -151,7 +155,7 @@ contract("TrackedRedemption", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -207,8 +211,8 @@ contract("TrackedRedemption", async (accounts) => { // Jump time await increaseTime(5000); - // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + // issue some tokens + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -233,8 +237,8 @@ contract("TrackedRedemption", async (accounts) => { "Failed in adding the investor in whitelist" ); - // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + // issue some tokens + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); diff --git a/test/w_lockup_transfer_manager.js b/test/w_lockup_transfer_manager.js index 7e0a59ae2..d7bc6b76f 100644 --- a/test/w_lockup_transfer_manager.js +++ b/test/w_lockup_transfer_manager.js @@ -9,6 +9,7 @@ const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const LockUpTransferManager = artifacts.require('./LockUpTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require('web3'); let BN = Web3.utils.BN; @@ -49,6 +50,9 @@ contract('LockUpTransferManager', accounts => { let I_SecurityToken_div; let I_GeneralTransferManager_div; let I_LockUpVolumeRestrictionTM_div; + let I_STGetter; + let stGetter; + let stGetter_div; // SecurityToken Details const name = "Team"; @@ -96,7 +100,8 @@ contract('LockUpTransferManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 4(c): Deploy the LockUpVolumeRestrictionTMFactory @@ -141,7 +146,7 @@ contract('LockUpTransferManager', accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -154,7 +159,7 @@ contract('LockUpTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); it("Should register another ticker before the generation of new security token", async () => { @@ -173,6 +178,7 @@ contract('LockUpTransferManager', accounts => { assert.equal(tx.logs[2].args._ticker, symbol2.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken_div = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); + stGetter_div = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken_div.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -185,7 +191,7 @@ contract('LockUpTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken_div.getModulesByType(2))[0]; + let moduleData = (await stGetter_div.getModulesByType(2))[0]; I_GeneralTransferManager_div = GeneralTransferManager.at(moduleData); }); @@ -212,7 +218,7 @@ contract('LockUpTransferManager', accounts => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei('2', 'ether')), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei('2', 'ether')), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor1)).toString(), @@ -235,7 +241,7 @@ contract('LockUpTransferManager', accounts => { 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 }); + await I_SecurityToken.issue(account_investor2, web3.utils.toWei('10', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor2)).toString(), @@ -305,7 +311,7 @@ contract('LockUpTransferManager', accounts => { // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, web3.utils.toWei('10', 'ether'), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, web3.utils.toWei('10', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor3)).toString(), @@ -523,7 +529,7 @@ contract('LockUpTransferManager', accounts => { 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 }); + await I_SecurityToken.issue(account_investor2, web3.utils.toWei('5', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor2)).toString(), @@ -662,9 +668,27 @@ contract('LockUpTransferManager', accounts => { // increase 20 sec that makes 1 period passed // 2 from a period and 1 is already unlocked await increaseTime(21); + console.log(`\t Total balance: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString())}`); + console.log(`\t Locked balance: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`LOCKED`))).toString())}`); + console.log(`\t Unlocked balance: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`UNLOCKED`))).toString())}`); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) }) + it("Should check the balance of the locked tokens", async() => { + console.log(`\t Total balance: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString())}`); + console.log(`\t Locked balance: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`LOCKED`))).toString())}`); + console.log(`\t Unlocked balance: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`UNLOCKED`))).toString())}`); + assert.equal( + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString()), + web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`LOCKED`))).toString()) + ); + console.log(`\t Wrong partition: ${web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.toHex(`OCKED`))).toString())}`); + assert.equal( + web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.toHex(`OCKED`))).toString()), + 0 + ); + }); + 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 @@ -673,6 +697,15 @@ contract('LockUpTransferManager', accounts => { await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) ) + let lockedBalance = web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`LOCKED`))).toString()); + let unlockedBalance = web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`UNLOCKED`))).toString()); + console.log(`\t Total balance: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString())}`); + console.log(`\t Locked balance: ${lockedBalance}`); + console.log(`\t Unlocked Balance: ${unlockedBalance}`); + assert.equal( + web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString()), + parseInt(lockedBalance) + parseInt(unlockedBalance) + ); // second txn will pass because 1 token is in unlocked state await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1'), { from: account_investor3 }) }); @@ -682,11 +715,27 @@ contract('LockUpTransferManager', accounts => { // more token from the lockup 2 await increaseTime(21); + let lockedBalance = web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`LOCKED`))).toString()); + let unlockedBalance = web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`UNLOCKED`))).toString()); + console.log(`\t Total balance: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString())}`); + console.log(`\t Locked balance: ${lockedBalance}`); + console.log(` \t Unlocked Amount for lockup 1: ${web3.utils.fromWei(((await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("c_lockup")))[4]).toString())}`) + console.log(` \t Unlocked Amount for lockup 2: ${web3.utils.fromWei(((await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("d_lockup")))[4]).toString())}`) + console.log(`\t Unlocked Balance: ${unlockedBalance}`); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3'), { from: account_investor3 }) assert.equal( (await I_SecurityToken.balanceOf(account_investor3)).toString(), web3.utils.toWei('3', 'ether') ); + console.log("After transaction"); + lockedBalance = web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`LOCKED`))).toString()); + unlockedBalance = web3.utils.fromWei((await stGetter.balanceOfByPartition.call(account_investor3, web3.utils.utf8ToHex(`UNLOCKED`))).toString()); + console.log(`\t Total balance: ${web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor3)).toString())}`); + console.log(`\t Locked balance: ${lockedBalance}`); + console.log(` \t Unlocked Amount for lockup 1: ${web3.utils.fromWei(((await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("c_lockup")))[4]).toString())}`) + console.log(` \t Unlocked Amount for lockup 2: ${web3.utils.fromWei(((await I_LockUpTransferManager.getLockUp.call(web3.utils.fromAscii("d_lockup")))[4]).toString())}`) + console.log(`\t Unlocked Balance: ${unlockedBalance}`); }); it("Should remove multiple lockup --failed because of bad owner", async() => { @@ -726,7 +775,7 @@ 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}); + await I_SecurityToken.issue(account_investor3, web3.utils.toWei("9"), "0x0", {from: token_owner}); let tx = await I_LockUpTransferManager.addNewLockUpToUser( account_investor3, diff --git a/test/x_scheduled_checkpoints.js b/test/x_scheduled_checkpoints.js index 536ace060..6f0818b35 100644 --- a/test/x_scheduled_checkpoints.js +++ b/test/x_scheduled_checkpoints.js @@ -7,6 +7,7 @@ import { setUpPolymathNetwork, deployScheduleCheckpointAndVerified } from "./hel const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const ScheduledCheckpoint = artifacts.require("./ScheduledCheckpoint.sol"); +const STGetter = artifacts.require("./STGetter.sol") const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -42,6 +43,8 @@ contract("ScheduledCheckpoint", async (accounts) => { let I_PolyToken; let I_PolymathRegistry; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -88,7 +91,8 @@ contract("ScheduledCheckpoint", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 2: Deploy the ScheduleCheckpointModule @@ -129,7 +133,7 @@ contract("ScheduledCheckpoint", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -138,7 +142,7 @@ contract("ScheduledCheckpoint", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -206,7 +210,7 @@ contract("ScheduledCheckpoint", async (accounts) => { console.log("6: " + await latestTime()); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -214,8 +218,8 @@ contract("ScheduledCheckpoint", async (accounts) => { it("Should have checkpoint created with correct balances", async () => { let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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); + assert.equal((await stGetter.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 1)).toNumber(), 0); }); it("Should Buy some more tokens for account_investor2", async () => { @@ -243,7 +247,7 @@ contract("ScheduledCheckpoint", async (accounts) => { assert.isTrue(await latestTime() <= startTime + interval); // Mint some tokens - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -251,8 +255,8 @@ contract("ScheduledCheckpoint", async (accounts) => { it("No additional checkpoints created", async () => { let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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); + assert.equal((await stGetter.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 1)).toNumber(), 0); }); it("Add a new token holder - account_investor3", async () => { @@ -281,7 +285,7 @@ contract("ScheduledCheckpoint", async (accounts) => { // Add the Investor in to the whitelist // Mint some tokens - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("1", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("1", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); @@ -289,15 +293,15 @@ contract("ScheduledCheckpoint", async (accounts) => { it("Should have new checkpoint created with correct balances", async () => { let cp1 = await I_ScheduledCheckpoint.getSchedule(web3.utils.fromAscii("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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - 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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor3, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 2)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Should have correct balances for investor 3 after new checkpoint", async () => { @@ -318,20 +322,20 @@ contract("ScheduledCheckpoint", async (accounts) => { [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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - - 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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - - 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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor3, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 2)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + + assert.equal((await stGetter.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor2, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + + assert.equal((await stGetter.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor1, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); }); it("Manually update checkpoints", async () => { @@ -349,23 +353,23 @@ contract("ScheduledCheckpoint", async (accounts) => { [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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor3, 4)).toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); - - 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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor2, 4)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - - 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)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); - assert.equal((await I_SecurityToken.balanceOfAt(account_investor1, 4)).toString(), new BN(web3.utils.toWei("0.5", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor3, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 2)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor3, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor3, 4)).toString(), new BN(web3.utils.toWei("1.5", "ether")).toString()); + + assert.equal((await stGetter.balanceOfAt(account_investor2, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor2, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor2, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor2, 4)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + + assert.equal((await stGetter.balanceOfAt(account_investor1, 0)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 1)).toNumber(), 0); + assert.equal((await stGetter.balanceOfAt(account_investor1, 2)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor1, 3)).toString(), new BN(web3.utils.toWei("1", "ether")).toString()); + assert.equal((await stGetter.balanceOfAt(account_investor1, 4)).toString(), new BN(web3.utils.toWei("0.5", "ether")).toString()); }); it("Should get the permission", async () => { diff --git a/test/y_volume_restriction_tm.js b/test/y_volume_restriction_tm.js index 5fac4428a..e915aaa16 100644 --- a/test/y_volume_restriction_tm.js +++ b/test/y_volume_restriction_tm.js @@ -9,6 +9,7 @@ import { setUpPolymathNetwork, deployVRTMAndVerifyed } from "./helpers/createIns const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager.sol'); const VolumeRestrictionTM = artifacts.require('./VolumeRestrictionTM.sol'); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require('web3'); const BN = Web3.utils.BN; @@ -54,6 +55,8 @@ contract('VolumeRestrictionTransferManager', accounts => { let I_STRProxied; let I_PolyToken; let I_PolymathRegistry; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -154,7 +157,8 @@ contract('VolumeRestrictionTransferManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 5: Deploy the VolumeRestrictionTMFactory @@ -196,7 +200,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -205,7 +209,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -235,9 +239,9 @@ contract('VolumeRestrictionTransferManager', accounts => { ); // Mint some tokens and transferred to whitelisted addresses - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("40", "ether")), {from: token_owner}); - await I_SecurityToken.mint(account_investor2, new BN(web3.utils.toWei("30", "ether")), {from: token_owner}); - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("30", "ether")), {from: token_owner}); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("40", "ether")), "0x0", {from: token_owner}); + await I_SecurityToken.issue(account_investor2, new BN(web3.utils.toWei("30", "ether")), "0x0", {from: token_owner}); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("30", "ether")), "0x0", {from: token_owner}); // Check the balance of the investors let bal1 = await I_SecurityToken.balanceOf.call(account_investor1); @@ -249,6 +253,10 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should transfer the tokens freely without any restriction", async() => { + console.log( + await I_SecurityToken.canTransfer.call(account_investor3, new BN(web3.utils.toWei('5', 'ether')), "0x0", {from: account_investor1}) + ) + console.log(web3.utils.fromWei((await I_SecurityToken.balanceOf.call(account_investor1)).toString())); await I_SecurityToken.transfer(account_investor3, new BN(web3.utils.toWei('5', 'ether')), { from: account_investor1 }); let bal1 = await I_SecurityToken.balanceOf.call(account_investor3); // Verifying the balances @@ -677,8 +685,8 @@ contract('VolumeRestrictionTransferManager', accounts => { 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, new BN(web3.utils.toWei('.3', "ether")), "0x0", false); - assert.equal(result.toString(), 1); + let result = await I_VolumeRestrictionTM.verifyTransfer.call(account_investor1, account_investor3, new BN(web3.utils.toWei('.3', "ether")), "0x0"); + assert.equal(result[0].toString(), 1); // Perform the transaction console.log(` Gas estimation (Individual): ${await I_SecurityToken.transfer.estimateGas(account_investor3, new BN(web3.utils.toWei('.3', "ether")), {from: account_investor1})}` @@ -1165,7 +1173,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }) it("Should sell more tokens on the same day after changing the total supply", async() => { - await I_SecurityToken.mint(account_investor3, new BN(web3.utils.toWei("10")), {from: token_owner}); + await I_SecurityToken.issue(account_investor3, new BN(web3.utils.toWei("10")), "0x0", {from: token_owner}); let startTime = (await I_VolumeRestrictionTM.getIndividualRestriction.call(account_investor3))[1].toString(); let startTimedaily = (await I_VolumeRestrictionTM.getIndividualDailyRestriction.call(account_investor3))[1].toString(); @@ -1308,8 +1316,8 @@ contract('VolumeRestrictionTransferManager', accounts => { ); }); - it("Should mint some tokens to investor 4", async() => { - await I_SecurityToken.mint(account_investor4, new BN(web3.utils.toWei("20")), {from: token_owner}); + it("Should issue some tokens to investor 4", async() => { + await I_SecurityToken.issue(account_investor4, new BN(web3.utils.toWei("20")), "0x0", {from: token_owner}); }); it("Should add the default daily restriction successfully", async() => { diff --git a/test/z_blacklist_transfer_manager.js b/test/z_blacklist_transfer_manager.js index f34c3e9e9..c07e73a9e 100644 --- a/test/z_blacklist_transfer_manager.js +++ b/test/z_blacklist_transfer_manager.js @@ -8,6 +8,7 @@ import { catchRevert } from "./helpers/exceptions"; const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const BlacklistTransferManager = artifacts.require("./BlacklistTransferManager"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require('web3'); let BN = Web3.utils.BN; @@ -53,6 +54,8 @@ contract('BlacklistTransferManager', accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -103,7 +106,8 @@ contract('BlacklistTransferManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -152,7 +156,7 @@ contract('BlacklistTransferManager', accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -165,7 +169,7 @@ contract('BlacklistTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -228,7 +232,7 @@ contract('BlacklistTransferManager', accounts => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, web3.utils.toWei('5', 'ether'), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, web3.utils.toWei('5', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor1)).toString(), @@ -252,7 +256,7 @@ contract('BlacklistTransferManager', accounts => { 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 }); + await I_SecurityToken.issue(account_investor2, web3.utils.toWei('2', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor2)).toString(), @@ -275,7 +279,7 @@ contract('BlacklistTransferManager', accounts => { 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 }); + await I_SecurityToken.issue(account_investor3, web3.utils.toWei('2', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor3)).toString(), @@ -298,7 +302,7 @@ contract('BlacklistTransferManager', accounts => { 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 }); + await I_SecurityToken.issue(account_investor4, web3.utils.toWei('2', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor4)).toString(), @@ -321,7 +325,7 @@ contract('BlacklistTransferManager', accounts => { 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 }); + await I_SecurityToken.issue(account_investor5, web3.utils.toWei('2', 'ether'), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(account_investor5)).toString(), diff --git a/test/z_fuzz_test_adding_removing_modules_ST.js b/test/z_fuzz_test_adding_removing_modules_ST.js index fbec6e51b..e527aed32 100644 --- a/test/z_fuzz_test_adding_removing_modules_ST.js +++ b/test/z_fuzz_test_adding_removing_modules_ST.js @@ -22,7 +22,7 @@ const CountTransferManager = artifacts.require("./CountTransferManager"); const ManualApprovalTransferManager = artifacts.require('./ManualApprovalTransferManager'); const VolumeRestrictionTransferManager = artifacts.require('./LockUpTransferManager'); const PercentageTransferManager = artifacts.require('./PercentageTransferManager'); - +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require('web3'); @@ -68,6 +68,8 @@ contract('GeneralPermissionManager', accounts => { let I_STRProxied; let I_PolyToken; let I_PolymathRegistry; + let I_STGetter; + let stGetter; //Define all modules for test @@ -145,7 +147,8 @@ contract('GeneralPermissionManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory @@ -195,7 +198,7 @@ contract('GeneralPermissionManager', accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -204,7 +207,7 @@ contract('GeneralPermissionManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); diff --git a/test/z_fuzzer_volumn_restriction_transfer_manager.js b/test/z_fuzzer_volumn_restriction_transfer_manager.js index 2f0a80195..007a09849 100644 --- a/test/z_fuzzer_volumn_restriction_transfer_manager.js +++ b/test/z_fuzzer_volumn_restriction_transfer_manager.js @@ -9,7 +9,7 @@ import { setUpPolymathNetwork, deployVRTMAndVerifyed } from "./helpers/createIns const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager.sol'); const VolumeRestrictionTM = artifacts.require('./VolumeRestrictionTM.sol'); - +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require('web3'); const BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port @@ -54,6 +54,8 @@ contract('VolumeRestrictionTransferManager', accounts => { let I_STRProxied; let I_PolyToken; let I_PolymathRegistry; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -141,7 +143,8 @@ contract('VolumeRestrictionTransferManager', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 5: Deploy the VolumeRestrictionTMFactory @@ -184,7 +187,7 @@ contract('VolumeRestrictionTransferManager', accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -193,7 +196,7 @@ contract('VolumeRestrictionTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -223,9 +226,9 @@ contract('VolumeRestrictionTransferManager', accounts => { ); // Mint some tokens and transferred to whitelisted addresses - 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}); + await I_SecurityToken.issue(account_investor1, web3.utils.toWei("100", "ether"), "0x0", {from: token_owner}); + await I_SecurityToken.issue(account_investor2, web3.utils.toWei("30", "ether"), "0x0", {from: token_owner}); + await I_SecurityToken.issue(account_investor3, web3.utils.toWei("30", "ether"), "0x0", {from: token_owner}); }); diff --git a/test/z_general_permission_manager_fuzzer.js b/test/z_general_permission_manager_fuzzer.js index 86d723299..b74fd254b 100644 --- a/test/z_general_permission_manager_fuzzer.js +++ b/test/z_general_permission_manager_fuzzer.js @@ -21,6 +21,7 @@ const CountTransferManager = artifacts.require("./CountTransferManager"); const VolumeRestrictionTransferManager = artifacts.require("./VolumeRestrictionTM"); const PercentageTransferManager = artifacts.require("./PercentageTransferManager"); const ManualApprovalTransferManager = artifacts.require("./ManualApprovalTransferManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); let BN = Web3.utils.BN; @@ -74,6 +75,8 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { let I_ManualApprovalTransferManagerFactory; let I_ManualApprovalTransferManager; let I_STRGetter; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -138,7 +141,8 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, I_STRProxied, - I_STRGetter + I_STRGetter, + I_STGetter ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory @@ -189,7 +193,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -198,7 +202,7 @@ contract("GeneralPermissionManager Fuzz", async (accounts) => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); diff --git a/test/z_vesting_escrow_wallet.js b/test/z_vesting_escrow_wallet.js index c80744dc5..02ce65b8f 100644 --- a/test/z_vesting_escrow_wallet.js +++ b/test/z_vesting_escrow_wallet.js @@ -9,7 +9,7 @@ const SecurityToken = artifacts.require('./SecurityToken.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const VestingEscrowWallet = artifacts.require('./VestingEscrowWallet.sol'); - +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require('web3'); const BN = Web3.utils.BN; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));// Hardcoded development port @@ -50,6 +50,8 @@ contract('VestingEscrowWallet', accounts => { let I_SecurityToken; let I_PolyToken; let I_PolymathRegistry; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -101,7 +103,8 @@ contract('VestingEscrowWallet', accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralDelegateManagerFactory @@ -147,7 +150,7 @@ contract('VestingEscrowWallet', accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -156,7 +159,7 @@ contract('VestingEscrowWallet', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); @@ -207,7 +210,7 @@ contract('VestingEscrowWallet', accounts => { 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.toHex(web3.utils.toWei('1', 'ether')), { from: token_owner }); + await I_SecurityToken.issue(token_owner, web3.utils.toHex(web3.utils.toWei('1', 'ether')), "0x0", { from: token_owner }); assert.equal( (await I_SecurityToken.balanceOf(token_owner)).toString(), diff --git a/test/zb_signed_transfer_manager.js b/test/zb_signed_transfer_manager.js index 98a81ca35..7dbb4f2e6 100644 --- a/test/zb_signed_transfer_manager.js +++ b/test/zb_signed_transfer_manager.js @@ -12,6 +12,7 @@ const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); const SignedTransferManager = artifacts.require("./SignedTransferManager"); +const STGetter = artifacts.require("./STGetter.sol"); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -50,6 +51,8 @@ contract("SignedTransferManager", accounts => { let I_SignedTransferManagerFactory; let P_SignedTransferManagerFactory; let I_SignedTransferManager; + let I_STGetter; + let stGetter; // SecurityToken Details const name = "Team"; @@ -96,7 +99,8 @@ contract("SignedTransferManager", accounts => { I_STFactory, I_SecurityTokenRegistry, I_SecurityTokenRegistryProxy, - I_STRProxied + I_STRProxied, + I_STGetter ] = instances; // STEP 2: Deploy the GeneralPermissionManagerFactory @@ -140,7 +144,7 @@ contract("SignedTransferManager", accounts => { assert.equal(tx.logs[2].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); I_SecurityToken = await SecurityToken.at(tx.logs[2].args._securityTokenAddress); - + stGetter = await STGetter.at(I_SecurityToken.address); const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0]; // Verify that GeneralTransferManager module get added successfully or not @@ -149,7 +153,7 @@ contract("SignedTransferManager", accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + let moduleData = (await stGetter.getModulesByType(2))[0]; I_GeneralTransferManager = await GeneralTransferManager.at(moduleData); }); }); @@ -180,7 +184,7 @@ contract("SignedTransferManager", accounts => { await increaseTime(5000); // Mint some tokens - await I_SecurityToken.mint(account_investor1, new BN(web3.utils.toWei("2", "ether")), { from: token_owner }); + await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString()); }); diff --git a/yarn.lock b/yarn.lock index 04adc5fef..1cb06e635 100644 --- a/yarn.lock +++ b/yarn.lock @@ -78,6 +78,8 @@ abbrev@1: abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" +<<<<<<< HEAD +======= abi-decoder@^1.0.8: version "1.2.0" @@ -85,6 +87,7 @@ abi-decoder@^1.0.8: integrity sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg== dependencies: web3 "^0.18.4" +>>>>>>> dev-3.0.0 abstract-leveldown@~2.6.0: version "2.6.3" @@ -169,6 +172,8 @@ ajv@^6.5.3: ajv@^6.5.5: version "6.6.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" +<<<<<<< HEAD +======= dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -178,6 +183,7 @@ ajv@^6.5.5: ajv@^6.9.1: version "6.9.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1" +>>>>>>> dev-3.0.0 dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -297,11 +303,14 @@ array-unique@^0.2.1: array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" +<<<<<<< HEAD +======= asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= +>>>>>>> dev-3.0.0 asn1.js@^4.0.0: version "4.10.1" @@ -1416,6 +1425,8 @@ chalk@^1.1.3: chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" +<<<<<<< HEAD +======= dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1424,6 +1435,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1: chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" +>>>>>>> dev-3.0.0 dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1606,6 +1618,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" + commander@2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -1639,6 +1655,8 @@ component-emitter@^1.2.1: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +<<<<<<< HEAD +======= concat-stream@^1.4.6, concat-stream@^1.6.0: version "1.6.2" @@ -1649,6 +1667,7 @@ concat-stream@^1.4.6, concat-stream@^1.6.0: inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" +>>>>>>> dev-3.0.0 console-browserify@^1.1.0: version "1.1.0" @@ -2141,8 +2160,13 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-crypto-utils "^1.0.0" emoji-regex@^7.0.1: +<<<<<<< HEAD + version "7.0.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.1.tgz#5a132b28ebf84a289ba692862f7d4206ebcd32d0" +======= version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" +>>>>>>> dev-3.0.0 emojis-list@^2.0.0: version "2.1.0" @@ -2419,6 +2443,15 @@ espree@^4.0.0: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" +<<<<<<< HEAD +esprima-extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" + dependencies: + esprima "^4.0.0" + +======= +>>>>>>> dev-3.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" @@ -2886,6 +2919,16 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +<<<<<<< HEAD +extract-comments@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" + dependencies: + esprima-extract-comments "^1.1.0" + parse-code-context "^1.0.0" + +======= +>>>>>>> dev-3.0.0 extract-opts@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/extract-opts/-/extract-opts-2.2.0.tgz#1fa28eba7352c6db480f885ceb71a46810be6d7d" @@ -3170,11 +3213,14 @@ 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" +<<<<<<< HEAD +======= get-port@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= +>>>>>>> dev-3.0.0 get-stream@^2.2.0: version "2.3.1" @@ -3450,6 +3496,8 @@ 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" +<<<<<<< HEAD +======= http-basic@^7.0.0: version "7.0.0" @@ -3462,6 +3510,7 @@ http-basic@^7.0.0: concat-stream "^1.4.6" http-response-object "^3.0.1" parse-cache-control "^1.0.1" +>>>>>>> dev-3.0.0 http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: version "1.6.3" @@ -3475,6 +3524,8 @@ 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" +<<<<<<< HEAD +======= http-response-object@^3.0.1: version "3.0.1" @@ -3482,6 +3533,7 @@ http-response-object@^3.0.1: integrity sha512-6L0Fkd6TozA8kFSfh9Widst0wfza3U1Ex2RjJ6zNDK0vR1U1auUR6jY4Nn2Xl7CCy0ikFmxW1XcspVpb9RvwTg== dependencies: "@types/node" "^9.3.0" +>>>>>>> dev-3.0.0 http-signature@~1.2.0: version "1.2.0" @@ -4955,10 +5007,16 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" +<<<<<<< HEAD +parse-code-context@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" +======= parse-cache-control@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" integrity sha1-juqz5U+laSD+Fro493+iGqzC104= +>>>>>>> dev-3.0.0 parse-glob@^3.0.4: version "3.0.4" @@ -5123,6 +5181,20 @@ prepend-http@^1.0.1: preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +<<<<<<< HEAD + +prettier-plugin-solidity-refactor@^1.0.0-alpha.10: + version "1.0.0-alpha.10" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity-refactor/-/prettier-plugin-solidity-refactor-1.0.0-alpha.10.tgz#39c783d9bae100792a71dbd9b60277fbc5cfa31b" + dependencies: + emoji-regex "^7.0.1" + escape-string-regexp "^1.0.5" + extract-comments "^1.1.0" + prettier "^1.15.2" + solidity-parser-antlr "^0.3.1" + string-width "3.0.0" +======= +>>>>>>> dev-3.0.0 prettier@^1.15.3: version "1.15.3" @@ -5225,11 +5297,14 @@ punycode@^2.1.0, punycode@^2.1.1: qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" +<<<<<<< HEAD +======= qs@^6.4.0: version "6.6.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2" integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA== +>>>>>>> dev-3.0.0 query-string@^5.0.1: version "5.1.1" @@ -5574,11 +5649,14 @@ resolve-from@^1.0.0: resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" +<<<<<<< HEAD +======= resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +>>>>>>> dev-3.0.0 resolve-url@^0.2.1: version "0.2.1" @@ -5996,6 +6074,19 @@ solc@^0.4.19, solc@^0.4.2: semver "^5.3.0" yargs "^4.7.1" +solc@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.2.tgz#45d5d11569e41c2b2535f3a50fe0616ca771a347" + dependencies: + command-exists "^1.2.8" + fs-extra "^0.30.0" + keccak "^1.0.2" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + yargs "^11.0.0" + solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" @@ -6023,10 +6114,16 @@ solidity-docgen@^0.1.0: react-dom "^16.2.0" shelljs "^0.8.1" +<<<<<<< HEAD +solidity-parser-antlr@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.3.2.tgz#1cf9d019280550a31299dc380e87a310dc4ca154" +======= solidity-parser-antlr@^0.2.10: version "0.2.15" resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.2.15.tgz#4be687a0a53da268c6a07398e0cfb3168896d610" integrity sha512-EzRI8/TR/ljTXkZAyAjb0w4G20wH2XM7pcNf87ifdV825AbUv7DkY7HmiZCTj6NeKtIx8Y1s0NZWPbj+JTp8Zw== +>>>>>>> dev-3.0.0 solidity-parser-sc@0.4.11: version "0.4.11" @@ -6211,6 +6308,17 @@ 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" +<<<<<<< HEAD + +string-width@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.0.0" +======= +>>>>>>> dev-3.0.0 string-width@^1.0.1: version "1.0.2" @@ -6467,6 +6575,8 @@ 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" +<<<<<<< HEAD +======= then-request@^6.0.0: version "6.0.0" @@ -6484,6 +6594,7 @@ then-request@^6.0.0: http-response-object "^3.0.1" promise "^8.0.0" qs "^6.4.0" +>>>>>>> dev-3.0.0 thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" @@ -6528,7 +6639,7 @@ tingodb@^0.6.1: optionalDependencies: bson "^1.0.4" -tmp@^0.0.33: +tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" dependencies: @@ -6637,10 +6748,16 @@ truffle-wallet-provider@0.0.5: web3 "^0.18.2" web3-provider-engine "^8.4.0" +<<<<<<< HEAD +truffle@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.0.tgz#2e4e2eedc5583ae38c7227585e5177d6360fbc6d" +======= truffle@^5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.4.tgz#fc68cb6a6a35b46a7ca69eca7b64d161b491db3d" integrity sha512-pZYFbU10Hb6PiTalJm+dB6s1qIZjE5qc0ux5fIgQ7Nj24zDrlYmOYruP3yhuqywwzr3PUHGPxr6hXuje0BFYoA== +>>>>>>> dev-3.0.0 dependencies: app-module-path "^2.2.0" mocha "^4.1.0" From 4f2ff43ddf1a8faf6a5be04c6574fffaf7976285 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 13:03:24 +0530 Subject: [PATCH 113/119] refactored some test cases --- test/g_general_permission_manager.js | 1 - test/helpers/signData.js | 20 -------- test/helpers/time.js | 73 +++++++++------------------- 3 files changed, 24 insertions(+), 70 deletions(-) diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index a4f8bcc0d..6e836fb33 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -1,5 +1,4 @@ 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"; diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 0d675d7a7..649f8a2c5 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -1,25 +1,6 @@ -const ethers = require("ethers"); -const utils = ethers.utils; -const ethUtil = require("ethereumjs-util"); const Web3 = require("web3"); let BN = Web3.utils.BN; -//this, _investor, _fromTime, _toTime, _validTo -function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, validFrom, validTo, nonce, pk) { - let packedData = utils - .solidityKeccak256( - ["address", "address", "uint256", "uint256", "uint256", "uint256", "uint256", "uint256"], - [tmAddress, investorAddress, fromTime, toTime, expiryTime, validFrom, validTo, nonce] - ) - .slice(2); - packedData = new Buffer(packedData, "hex"); - console.log("PackedData 1: " + packedData); - packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); - packedData = web3.utils.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); - console.log("PackedData 2: " + packedData); - return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); -} - function getSignSTMData(tmAddress, nonce, expiry, fromAddress, toAddress, amount, pk) { let hash = web3.utils.soliditySha3({t: 'address', v: tmAddress}, {t: 'uint256', v: new BN(nonce)}, {t: 'uint256', v: new BN(expiry)}, {t: 'address', v: fromAddress}, {t: 'address', v: toAddress}, {t: 'uint256', v: new BN(amount)}); let signature = (web3.eth.accounts.sign(hash, pk)).signature; @@ -34,7 +15,6 @@ function getSignGTMData(tmAddress, investorAddress, fromTime, toTime, expiryTime } module.exports = { - signData, getSignSTMData, getSignGTMData }; diff --git a/test/helpers/time.js b/test/helpers/time.js index 1bbe676ca..f30f73409 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -2,66 +2,41 @@ // aren’t included within the original RPC specification. // See https://github.com/ethereumjs/testrpc#implemented-methods -// async function increaseTime(duration) { -// //let currentTime = (await web3.eth.getBlock('latest')).timestamp -// await sendIncreaseTime(duration); -// return advanceBlock(); -// } - -// async function sendIncreaseTime(duration) { -// return new Promise(() => -// web3.currentProvider.send({ -// jsonrpc: '2.0', -// method: 'evm_increaseTime', -// params: [duration], -// }) -// ); -// } - -// async function advanceBlock() { -// return new Promise(() => -// web3.currentProvider.send({ -// jsonrpc: '2.0', -// method: 'evm_mine', -// }) -// ); -// } - const pify = require('pify'); -function advanceBlock() { - return pify(web3.currentProvider.send)({ - jsonrpc: '2.0', - method: 'evm_mine', +async function advanceBlock() { + return new Promise((resolve, reject) => { + web3.currentProvider.send({ + jsonrpc: '2.0', + method: 'evm_mine', + }, + (err, result) => { + if (err) { + return reject(err); + } + resolve(result.result); + } + ); }); } // Increases ganache time by the passed duration in seconds async function increaseTime(duration) { - await pify(web3.currentProvider.send)({ - jsonrpc: '2.0', - method: 'evm_increaseTime', - params: [duration], - }); - await advanceBlock(); -} - -async 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 + await new Promise((resolve, reject) => { + web3.currentProvider.send({ + jsonrpc: '2.0', + method: 'evm_increaseTime', + params: [duration], }, - (err, res) => { - return err ? reject(err) : resolve(res); + (err, result) => { + if (err) { + return reject(err); + } + resolve(result.result); } ); }); + await advanceBlock(); } export default function takeSnapshot() { From ab017909b7b7a813a7028927f31c0e09e37e913c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 13:03:36 +0530 Subject: [PATCH 114/119] Cleanup dependencies --- package.json | 46 +- truffle-config-gas.js | 2 +- truffle-config.js | 2 +- yarn.lock | 3121 +++++++++++++++++------------------------ 4 files changed, 1331 insertions(+), 1840 deletions(-) diff --git a/package.json b/package.json index ede090493..4c4229b4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "polymath-core", - "version": "2.0.0", + "version": "3.0.0", "description": "Polymath Network Core Smart Contracts", "main": "truffle.js", "directories": { @@ -57,30 +57,10 @@ }, "homepage": "https://github.com/PolymathNetwork/polymath-core#readme", "dependencies": { - "babel-polyfill": "6.26.0", - "babel-preset-es2015": "6.24.1", - "babel-preset-stage-2": "6.24.1", - "babel-preset-stage-3": "6.24.1", - "babel-register": "6.26.0", - "bignumber.js": "5.0.0", - "chalk": "^2.4.2", - "coveralls": "^3.0.1", - "ethereumjs-testrpc": "^6.0.3", - "ethers": "^4.0.7", - "fs": "0.0.2", - "openzeppelin-solidity": "^2.1.0-rc.2", - "pify": "^4.0.1", - "prompt": "^1.0.0", - "readline-sync": "^1.4.9", - "request": "^2.88.0", - "request-promise": "^4.2.2", - "solc": "^0.5.2", - "truffle-contract": "^3.0.4", - "truffle-hdwallet-provider-privkey": "0.2.0", - "web3": "1.0.0-beta.35" + "truffle": "^5.0.4", + "truffle-hdwallet-provider": "^1.0.4" }, "devDependencies": { - "@soldoc/soldoc": "^0.4.3", "eslint": "^5.8.0", "eslint-config-standard": "^12.0.0", "eslint-plugin-import": "^2.10.0", @@ -92,21 +72,31 @@ "ethereumjs-abi": "^0.6.5", "ganache-cli": "^6.2.4", "mocha-junit-reporter": "^1.18.0", + "openzeppelin-solidity": "2.1.2", "prettier": "^1.15.3", - "table": "^5.2.3", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", "solium": "^1.1.6", - "truffle": "^5.0.4", - "truffle-wallet-provider": "0.0.5" + "table": "^5.2.3", + "babel-polyfill": "6.26.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-2": "6.24.1", + "babel-preset-stage-3": "6.24.1", + "babel-register": "6.26.0", + "chalk": "^2.4.2", + "coveralls": "^3.0.1", + "fs": "0.0.2", + "prompt": "^1.0.0", + "request": "^2.88.0", + "request-promise": "^4.2.2", + "web3": "1.0.0-beta.35" }, "greenkeeper": { "ignore": [ "openzeppelin-solidity", "web3", - "bignumber.js", - "truffle-hdwallet-provider-privkey" + "truffle-hdwallet-provider" ] } } diff --git a/truffle-config-gas.js b/truffle-config-gas.js index 8f690985f..edc6c325b 100644 --- a/truffle-config-gas.js +++ b/truffle-config-gas.js @@ -3,7 +3,7 @@ require('babel-polyfill'); const fs = require('fs'); const NonceTrackerSubprovider = require("web3-provider-engine/subproviders/nonce-tracker") -const HDWalletProvider = require("truffle-hdwallet-provider-privkey"); +const HDWalletProvider = require("truffle-hdwallet-provider"); module.exports = { networks: { diff --git a/truffle-config.js b/truffle-config.js index c6d636e97..21bfd6097 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -3,7 +3,7 @@ require('babel-polyfill'); const fs = require('fs'); const NonceTrackerSubprovider = require("web3-provider-engine/subproviders/nonce-tracker") -const HDWalletProvider = require("truffle-hdwallet-provider-privkey"); +const HDWalletProvider = require("truffle-hdwallet-provider"); module.exports = { networks: { diff --git a/yarn.lock b/yarn.lock index 1cb06e635..6206a8dfb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,34 +5,19 @@ "@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" 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/concat-stream@^1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.0.tgz#394dbe0bb5fee46b38d896735e8b68ef2390d00d" @@ -48,13 +33,9 @@ "@types/node" "*" "@types/node@*": - version "11.9.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.3.tgz#14adbb5ab8cd563f549fbae8dbe92e0b7d6e76cc" - integrity sha512-DMiqG51GwES/c4ScBY0u5bDlH44+oY8AeYHjY1SGCWidD7h08o1dfHue/TGK7REmif2KiJzaUskO+Q0eaeZ2fQ== - -"@types/node@^10.3.2": - version "10.12.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.2.tgz#d77f9faa027cadad9c912cd47f4f8b07b0fb0864" + version "11.9.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.4.tgz#ceb0048a546db453f6248f2d1d95e937a6f00a14" + integrity sha512-Zl8dGvAcEmadgs1tmSPcvwzO1YRsz38bVJQvH1RvRqSR9/5n61Q1ktcDL0ht3FXWR+ZpVmXVwN1LuH4Ax23NsA== "@types/node@^8.0.0": version "8.10.40" @@ -74,12 +55,12 @@ 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" -<<<<<<< HEAD -======= + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= abi-decoder@^1.0.8: version "1.2.0" @@ -87,120 +68,49 @@ abi-decoder@^1.0.8: integrity sha512-y2OKSEW4gf2838Eavc56vQY9V46zaXkf3Jl1WpTfUBbzAVrXSr4JRZAAWv55Tv9s5WNz1rVgBgz5d2aJIL1QCg== dependencies: web3 "^0.18.4" ->>>>>>> dev-3.0.0 - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - 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" - 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@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.0.tgz#958584ddb60990c02c97c1bd9d521fce433bb101" - -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@^6.0.2: - version "6.0.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754" - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - -aes-js@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + 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== -ajv-keywords@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" +acorn@^6.0.7: + version "6.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" + integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw== -ajv@^5.1.1, ajv@^5.2.2: +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" - 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" - -ajv@^6.5.3: - version "6.5.5" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.5.tgz#cf97cdade71c6399a92c6d6c4177381291b781a1" - 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" - -ajv@^6.5.5: - version "6.6.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" -<<<<<<< HEAD -======= - 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" - -ajv@^6.9.1: +ajv@^6.5.5, ajv@^6.9.1: version "6.9.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1" ->>>>>>> dev-3.0.0 + integrity sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA== 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" @@ -208,62 +118,67 @@ 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" +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== 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" -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" - app-module-path@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= 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" @@ -271,50 +186,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" 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" -<<<<<<< HEAD -======= + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= ->>>>>>> dev-3.0.0 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" @@ -323,92 +244,90 @@ 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" - -async-eventemitter@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - dependencies: - async "^2.4.0" - -async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: - version "0.2.3" - resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" - dependencies: - async "^2.4.0" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= 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: +async@1.x, 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" +async@^2.4.1, async@^2.5.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== dependencies: - lodash "^4.17.10" + lodash "^4.17.11" 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" js-tokens "^3.0.2" -babel-core@^6.0.14, babel-core@^6.26.0: +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" @@ -433,6 +352,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" @@ -446,6 +366,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" @@ -454,6 +375,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" @@ -462,6 +384,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" @@ -471,6 +394,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" @@ -480,6 +404,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" @@ -488,6 +413,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" @@ -497,6 +423,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" @@ -507,6 +434,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" @@ -514,6 +442,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" @@ -521,6 +450,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" @@ -528,6 +458,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" @@ -536,6 +467,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" @@ -546,6 +478,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" @@ -557,6 +490,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" @@ -564,58 +498,70 @@ 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" babel-runtime "^6.22.0" -babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: +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" @@ -624,6 +570,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" @@ -633,6 +580,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" @@ -643,18 +591,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: +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" @@ -662,9 +613,10 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-types "^6.26.0" lodash "^4.17.4" -babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: +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" @@ -676,35 +628,40 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: +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" -babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: +babel-plugin-transform-es2015-destructuring@^6.22.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: +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" -babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: +babel-plugin-transform-es2015-for-of@^6.22.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: +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" @@ -713,52 +670,59 @@ 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: +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" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: +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" babel-template "^6.26.0" babel-types "^6.26.0" -babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: +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" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: +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" babel-template "^6.24.1" -babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: +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" -babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: +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" @@ -767,9 +731,10 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: +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" @@ -777,12 +742,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: +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" @@ -791,26 +758,30 @@ 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: +babel-plugin-transform-es2015-typeof-symbol@^6.22.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: +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" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: +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" @@ -819,19 +790,22 @@ 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" -babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: +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" @@ -839,49 +813,16 @@ 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" regenerator-runtime "^0.10.5" -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" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.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" @@ -911,6 +852,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" @@ -920,6 +862,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" @@ -930,6 +873,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" @@ -942,6 +886,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" @@ -949,6 +894,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" @@ -959,6 +905,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" @@ -973,44 +920,39 @@ 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" lodash "^4.17.4" to-fast-properties "^1.0.3" -babelify@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.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" - 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" @@ -1023,28 +965,19 @@ 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" - 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@^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" - resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9" +bignumber.js@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.0.2.tgz#d8c4e1874359573b1ef03011a2d861214aeef137" + integrity sha512-EiuvFrnbv0jFixEQ9f58jo7X0qI2lNGIr/MxntmVzQc5JUweDSh8y8hbTCAomFtqwUPIOWcLXP0VEOSZTG7FFw== "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": version "2.0.7" @@ -1055,22 +988,28 @@ bignumber.js@^7.2.1: resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" binary-extensions@^1.0.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" + version "1.13.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" + integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== -bindings@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" +bindings@^1.2.1, 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" @@ -1082,6 +1021,7 @@ 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" @@ -1093,6 +1033,7 @@ 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" @@ -1100,6 +1041,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" @@ -1107,32 +1049,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, 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: +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.1, 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" @@ -1146,17 +1095,20 @@ body-parser@1.18.3, body-parser@^1.16.0: type-is "~1.6.16" borc@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/borc/-/borc-2.0.4.tgz#52926dc561137188c6ca9fe01c9542576529a689" + version "2.1.0" + resolved "https://registry.yarnpkg.com/borc/-/borc-2.1.0.tgz#2def2fc69868633b965a9750e7f210d778190303" + integrity sha512-hKTxeYt3AIzIG45epJHv8xJYSF0ktp7nZgFsqi5cPzoL3T8qKMPeUlqydORy6j3NWZvRDANx30PjpTmGho69Gw== dependencies: - bignumber.js "^7.2.1" + bignumber.js "^8.0.1" commander "^2.15.0" ieee754 "^1.1.8" - json-text-sequence "^0.1" + iso-url "~0.4.4" + json-text-sequence "~0.1.0" 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" @@ -1164,14 +1116,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" @@ -1187,18 +1141,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" @@ -1210,6 +1168,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" @@ -1218,6 +1177,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" @@ -1227,19 +1187,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" @@ -1249,48 +1213,27 @@ 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" - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - -bs58@=4.0.1, bs58@^4.0.0, bs58@^4.0.1: +bs58@=4.0.1, 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" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.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" @@ -1298,65 +1241,59 @@ 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" - 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" isarray "^1.0.0" -buffer@^5.0.5: +buffer@^5.0.5, buffer@^5.2.1: 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" -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" - 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" @@ -1368,53 +1305,38 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - 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" +callsites@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" + integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== 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.30000921" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000921.tgz#7a607c1623444b22351d834e093aedda3c42fbe8" - 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" @@ -1422,20 +1344,10 @@ 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: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" -<<<<<<< HEAD -======= - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" ->>>>>>> dev-3.0.0 + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1444,20 +1356,17 @@ chalk@^2.4.2: 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", charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - dependencies: - functional-red-black-tree "^1.0.1" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= 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" @@ -1470,43 +1379,23 @@ 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.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" -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - 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" @@ -1516,6 +1405,7 @@ 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" @@ -1527,6 +1417,7 @@ 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" @@ -1543,18 +1434,12 @@ cli-table3@^0.5.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" @@ -1563,33 +1448,31 @@ 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" wrap-ansi "^2.0.0" -clone@2.x, clone@^2.0.0: +clone@2.x: 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" - -coinstring@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - dependencies: - bs58 "^2.0.1" - create-hash "^1.1.1" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 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" @@ -1597,66 +1480,73 @@ 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, 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" -command-exists@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" - 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" -<<<<<<< HEAD -======= + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.4.6, concat-stream@^1.6.0: version "1.6.2" @@ -1667,67 +1557,68 @@ concat-stream@^1.4.6, concat-stream@^1.6.0: inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" ->>>>>>> dev-3.0.0 - -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" 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.6.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.0.tgz#1e30793e9ee5782b307e37ffa22da0eacddd84d4" + version "2.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895" + integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A== 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" @@ -1735,6 +1626,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" @@ -1746,13 +1638,15 @@ 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" -create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: +create-hash@^1.1.0, 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" @@ -1763,6 +1657,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" @@ -1774,6 +1669,7 @@ 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" @@ -1781,6 +1677,7 @@ 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" @@ -1789,6 +1686,7 @@ 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,10 +1697,12 @@ cross-spawn@^6.0.5: "crypt@>= 0.0.1", 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: +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" @@ -1819,84 +1719,91 @@ 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== 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-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" + 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.1.0, debug@^3.2.6: +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" + 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" @@ -1905,6 +1812,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" @@ -1915,6 +1823,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" @@ -1923,6 +1832,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" @@ -1932,6 +1842,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" @@ -1942,82 +1853,74 @@ 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" - -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-hLdFiW80xoTpjyzg5Cq69Du6AX0= 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" - dependencies: - abstract-leveldown "~2.6.0" - -define-properties@^1.1.1, define-properties@^1.1.2: +define-properties@^1.1.1: 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" -defined@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - 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" @@ -2025,28 +1928,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: +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" @@ -2055,27 +1964,27 @@ 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" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 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" @@ -2084,51 +1993,45 @@ 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" -editions@^1.1.1, editions@^1.3.3, editions@^1.3.4: +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: - version "2.1.0" - resolved "https://registry.yarnpkg.com/editions/-/editions-2.1.0.tgz#5c6f6341ef19ee362a3bcbb907fe68e696dbc69e" +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.0.3" + errlop "^1.1.1" 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" - -electron-to-chromium@^1.3.47: - version "1.3.92" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.92.tgz#9027b5abaea400045edd652c0e4838675c814399" - -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 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" @@ -2141,6 +2044,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" @@ -2150,6 +2054,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" @@ -2160,130 +2065,71 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-crypto-utils "^1.0.0" emoji-regex@^7.0.1: -<<<<<<< HEAD - version "7.0.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.1.tgz#5a132b28ebf84a289ba692862f7d4206ebcd32d0" -======= version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" ->>>>>>> dev-3.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" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 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.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/errlop/-/errlop-1.0.3.tgz#dba29c90cf832c3d2ce469fe515d7e5eef2c6676" - 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" +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: - prr "~1.0.1" + editions "^2.1.2" 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" - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" - -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" - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - 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" + version "0.10.47" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.47.tgz#d24232e1380daad5449a817be19bde9729024a11" + integrity sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw== 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" @@ -2293,14 +2139,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" @@ -2309,58 +2158,55 @@ 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@^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: +eslint-import-resolver-node@^0.3.2: 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" -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" +eslint-module-utils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" + integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== dependencies: debug "^2.6.8" - pkg-dir "^1.0.0" + pkg-dir "^2.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" + 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: - version "2.14.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" + version "2.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f" + integrity sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A== dependencies: contains-path "^0.1.0" - debug "^2.6.8" + debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.2.0" - has "^1.0.1" - lodash "^4.17.4" - minimatch "^3.0.3" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.3.0" + has "^1.0.3" + lodash "^4.17.11" + minimatch "^3.0.4" read-pkg-up "^2.0.0" - resolve "^1.6.0" + resolve "^1.9.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" + version "8.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz#55ae3560022863d141fa7a11799532340a685964" + integrity sha512-ZjOjbjEi6jd82rIpFSgagv4CHWzG9xsQAVp1ZPlhRnnYxcTgENUVBvhYmkQ7GvT1QFijUSo69RaiOJKhMu6i8w== dependencies: eslint-plugin-es "^1.3.1" eslint-utils "^1.3.1" @@ -2372,14 +2218,17 @@ 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" @@ -2387,119 +2236,107 @@ 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.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.8.0.tgz#91fbf24f6e0471e8fdf681a4d9dd1b2c9f28309b" + version "5.14.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.14.1.tgz#490a28906be313685c55ccd43a39e8d22efc04ba" + integrity sha512-CyUMbmsjxedx8B0mr79mNOqetvkbij/zrXnFeK2zc3pGRn3/tibjiNAv/3UxFEyfMDjh+ZqTrJrEGBFiGfD5Og== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.5.3" + ajv "^6.9.1" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" - doctrine "^2.1.0" + doctrine "^3.0.0" eslint-scope "^4.0.0" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^4.0.0" + espree "^5.0.1" esquery "^1.0.1" esutils "^2.0.2" - file-entry-cache "^2.0.0" + file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" glob "^7.1.2" globals "^11.7.0" ignore "^4.0.6" + import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.1.0" - is-resolvable "^1.1.0" + inquirer "^6.2.2" js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.5" + lodash "^4.17.11" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^7.0.0" progress "^2.0.0" regexpp "^2.0.1" - require-uncached "^1.0.3" semver "^5.5.1" strip-ansi "^4.0.0" strip-json-comments "^2.0.1" - table "^5.0.2" + table "^5.2.3" text-table "^0.2.0" -espree@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== dependencies: - acorn "^6.0.2" + acorn "^6.0.7" acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" -<<<<<<< HEAD -esprima-extract-comments@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" - dependencies: - esprima "^4.0.0" - -======= ->>>>>>> dev-3.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" - -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" - dependencies: - async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eth-gas-reporter@^0.1.12: version "0.1.12" @@ -2522,6 +2359,7 @@ eth-gas-reporter@^0.1.12: 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" @@ -2534,6 +2372,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" @@ -2542,6 +2381,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" @@ -2555,23 +2395,10 @@ eth-lightwallet@^3.0.1: tweetnacl "0.13.2" web3 "0.20.2" -eth-query@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -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" - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - 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" @@ -2599,75 +2426,38 @@ ethereum-bridge@^0.6.1: web3 "0.19.1" winston "^2.3.1" -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - 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" -ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.5" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799" +ethereumjs-abi@^0.6.5: + version "0.6.6" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.6.tgz#f8ba3413a98478173f5a00f7f1316819db1d09ec" + integrity sha512-w8KubDsA/+OAuqtIR9RGsMcoZ5nhM8vxwjJAJvEIY+clhxA3BHoLG3+ClYQaQhD0n3mlDt3U5rBrmSVJvI3c8A== dependencies: bn.js "^4.10.0" ethereumjs-util "^5.0.0" -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - dependencies: - ethereumjs-util "^5.0.0" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-block@^1.2.2: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.1.0.tgz#71d1b19e18061f14cf6371bf34ba31a359931360" - 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" - 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: +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" @@ -2675,6 +2465,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" @@ -2682,9 +2473,10 @@ ethereumjs-util@^4.3.0: rlp "^2.0.0" secp256k1 "^3.0.1" -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: +ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, 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" @@ -2694,87 +2486,26 @@ 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" - 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.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.5.0.tgz#71dde54a093bd813c9defdc6d45ceb8fcca2f603" - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - 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" - rustbn.js "~0.2.0" - 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" - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereumjs-util "^5.2.0" - hdkey "^1.0.0" - safe-buffer "^5.1.2" - scrypt.js "^0.2.0" - utf8 "^3.0.0" - uuid "^3.3.2" - -ethers@^4.0.7: - version "4.0.9" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.9.tgz#82bb075b1b3da847d672426cb24685371389155d" - 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-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.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" -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" @@ -2782,18 +2513,12 @@ 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" - -events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha1-R3hr2qCHyvext15zq8XH1UAVjNA= 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" @@ -2801,6 +2526,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" @@ -2813,12 +2539,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" @@ -2831,12 +2559,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" @@ -2872,12 +2602,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" @@ -2885,16 +2617,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" + 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: +external-editor@^3.0.3: 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" @@ -2903,12 +2638,14 @@ 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" @@ -2919,100 +2656,98 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -<<<<<<< HEAD -extract-comments@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/extract-comments/-/extract-comments-1.1.0.tgz#b90bca033a056bd69b8ba1c6b6b120fc2ee95c18" - dependencies: - esprima-extract-comments "^1.1.0" - parse-code-context "^1.0.0" - -======= ->>>>>>> dev-3.0.0 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" - -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" - dependencies: - checkpoint-store "^1.1.0" + integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= 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" - 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" +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" + flat-cache "^2.0.1" 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" @@ -3023,6 +2758,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" @@ -3032,6 +2768,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" @@ -3044,6 +2781,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" @@ -3051,41 +2789,52 @@ 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" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: - circular-json "^0.3.1" - graceful-fs "^4.1.2" - rimraf "~2.6.2" - write "^0.2.1" + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" + integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== -for-each@^0.3.2, for-each@~0.3.3: +for-each@^0.3.2: 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.2.0, 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" @@ -3094,24 +2843,29 @@ form-data@^2.2.0, 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" @@ -3122,21 +2876,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@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - 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" @@ -3145,12 +2893,14 @@ 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" @@ -3160,14 +2910,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.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: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" +fsevents@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" + integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -3175,23 +2928,27 @@ 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" mkdirp ">=0.5 0" rimraf "2" -function-bind@^1.0.2, function-bind@^1.1.1, 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.4: - version "6.2.4" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.2.4.tgz#0ec3d5d993a85c9f252fb632105ab7ffe7668638" + version "6.3.0" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.3.0.tgz#574f9d35aaec8da6e01c2be49db8fe73129eb561" + integrity sha512-8SyzfX2ipRVBx1fBZLg3j8I3E334U3Vazk5mEpYcWqnIjC2ace6jtOXHG4aTuAvSz3+HzQ8p8pRjOJxdDZ2pnQ== dependencies: bn.js "4.11.8" source-map-support "0.5.9" @@ -3200,6 +2957,7 @@ ganache-cli@^6.2.4: 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" @@ -3213,18 +2971,17 @@ 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" -<<<<<<< HEAD -======= + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== get-port@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= ->>>>>>> dev-3.0.0 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" @@ -3232,20 +2989,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" @@ -3253,19 +3014,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" @@ -3277,6 +3033,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" @@ -3284,9 +3041,10 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: +glob@^7.0.0, glob@^7.1.2, glob@^7.1.3: 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" @@ -3298,6 +3056,7 @@ glob@^7.0.0, 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" @@ -3308,21 +3067,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.9.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" + version "11.11.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" + integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== 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" @@ -3342,22 +3105,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.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" + version "4.1.0" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a" + integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -3368,10 +3136,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.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" @@ -3379,42 +3149,46 @@ 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" - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== 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" @@ -3423,6 +3197,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" @@ -3431,56 +3206,48 @@ 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" -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" -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - 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" -hdkey@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" - dependencies: - coinstring "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - 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" @@ -3489,6 +3256,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" @@ -3496,8 +3264,7 @@ 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" -<<<<<<< HEAD -======= + integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== http-basic@^7.0.0: version "7.0.0" @@ -3510,11 +3277,11 @@ http-basic@^7.0.0: concat-stream "^1.4.6" http-response-object "^3.0.1" parse-cache-control "^1.0.1" ->>>>>>> dev-3.0.0 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" @@ -3524,8 +3291,7 @@ 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" -<<<<<<< HEAD -======= + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= http-response-object@^3.0.1: version "3.0.1" @@ -3533,23 +3299,20 @@ http-response-object@^3.0.1: integrity sha512-6L0Fkd6TozA8kFSfh9Widst0wfza3U1Ex2RjJ6zNDK0vR1U1auUR6jY4Nn2Xl7CCy0ikFmxW1XcspVpb9RvwTg== dependencies: "@types/node" "^9.3.0" ->>>>>>> dev-3.0.0 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" @@ -3561,40 +3324,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: +iconv-lite@^0.4.24, iconv-lite@^0.4.4: 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" + version "5.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" + integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== 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" @@ -3602,129 +3373,139 @@ 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" +import-fresh@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" + integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" 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" -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: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, 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@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" +inquirer@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" + integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" + ansi-escapes "^3.2.0" + chalk "^2.4.2" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^3.0.0" + external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.10" + lodash "^4.17.11" mute-stream "0.0.7" run-async "^2.2.0" - rxjs "^6.1.0" + rxjs "^6.4.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" + 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" - dependencies: - builtin-modules "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4: +is-callable@^1.1.3: 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" - 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" @@ -3733,6 +3514,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" @@ -3741,205 +3523,192 @@ 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" - -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" - 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-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" + 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" - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - 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" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= 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: +is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - dependencies: - has-symbols "^1.0.0" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 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" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== 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.6" + resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-0.4.6.tgz#45005c4af4984cad4f8753da411b41b74cf0a8a6" + integrity sha512-YQO7+aIe6l1aSJUKOx+Vrv08DlhZeLFIVfehG2L29KLSEb9RszqPXilxJRVpp57px36BddKR5ZsebacO5qG0tg== 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" - -isomorphic-fetch@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= 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" @@ -3959,37 +3728,35 @@ 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" - -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" + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" + integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -3997,95 +3764,73 @@ 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" - -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" - dependencies: - async "^2.0.1" - babel-preset-env "^1.7.0" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - -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" - 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-597mbjXW/Bb3EP6R1c9p9w8IkR0= 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" - -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" - dependencies: - jsonify "~0.0.0" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 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: +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.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" - 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" @@ -4095,6 +3840,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" @@ -4102,99 +3848,60 @@ 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" - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - 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" - 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" - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" + integrity sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM= 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" @@ -4202,6 +3909,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" @@ -4212,27 +3920,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" @@ -4240,44 +3938,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.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: +lodash@4.x, lodash@=4.17.11, lodash@^4.14.2, 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= -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: 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" @@ -4285,48 +3983,52 @@ 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" - 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" + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== 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" @@ -4335,6 +4037,7 @@ 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" @@ -4343,27 +4046,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" - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - 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" @@ -4374,37 +4069,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" - -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" - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= 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" @@ -4415,10 +4093,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" @@ -4434,9 +4114,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" @@ -4455,67 +4136,81 @@ 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.37.0: - version "1.37.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" +mime-db@~1.38.0: + version "1.38.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" + integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== 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" + version "2.1.22" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" + integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== dependencies: - mime-db "~1.37.0" + mime-db "~1.38.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: +"minimatch@2 || 3", minimatch@3.0.4, 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: +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" @@ -4523,12 +4218,14 @@ 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" @@ -4536,18 +4233,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@~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" 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" @@ -4558,6 +4258,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" @@ -4573,6 +4274,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" @@ -4587,34 +4289,41 @@ mocha@^5.0.1: supports-color "5.4.0" mock-fs@^4.1.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" + version "4.8.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.8.0.tgz#eb0784ceba4b34c91a924a5112eeb36e1b5a9e29" + integrity sha512-Gwj4KnJOW15YeTJKO5frFd/WDO5Mc0zxXqL9oHx3+e9rBqW8EVARqQHSaIXznUdljrD6pvbNGW2ZGXKPEfYJfw== 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" + version "2.24.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" + integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== 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" @@ -4622,18 +4331,27 @@ 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, 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= + +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" @@ -4642,18 +4360,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.12.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.0.tgz#9d443fdb5e13a20770cc5e602eee59760a685885" +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" @@ -4670,14 +4392,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 "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" @@ -4686,68 +4411,35 @@ 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.6.0" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" + 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" -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" - 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" @@ -4761,8 +4453,9 @@ node-pre-gyp@^0.10.0: tar "^4" node-schedule@^1.2.3: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.1.tgz#6909dd644211bca153b15afc62e1dc0afa7d28be" + version "1.3.2" + resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-1.3.2.tgz#d774b383e2a6f6ade59eecc62254aea07cd758cb" + integrity sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw== dependencies: cron-parser "^2.7.3" long-timeout "0.1.1" @@ -4771,38 +4464,44 @@ 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" 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" + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" + resolve "^1.10.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" + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== npm-packlist@^1.1.6: - version "1.1.12" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" + version "1.3.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.3.0.tgz#7f01e8e44408341379ca98cfd756e7b29bd2626c" + integrity sha512-qPBc6CnxEzpOcc4bjoIBJbYdy0D/LFFPUdxvfwor4/w3vxeE0h6TiOVurCEPpQ6trjN77u/ShyfeJGsbAfB3dA== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -4810,12 +4509,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" @@ -4825,10 +4526,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" @@ -4836,40 +4539,38 @@ 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: +object-assign@^4, 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-inspect@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - object-keys@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + version "1.1.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" + integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== 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" @@ -4877,40 +4578,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@^2.1.0-rc.2: - version "2.1.0-rc.2" - resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.1.0-rc.2.tgz#704b7c86cc45fc82bc23ab706d767d04cf3391dc" +openzeppelin-solidity@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-2.1.2.tgz#94e2bb92b60e91abb22c6fe27d983d92850fb324" + integrity sha512-1ggh+AZFpMAgGfgnVMQ8dwYawjD2QN4xuWkQS4FUbeUz1fnCKJpguUl2cyadyfDYjBq1XJ6MA6VkzYpTZtJMqw== 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" @@ -4918,6 +4626,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" @@ -4929,24 +4638,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" @@ -4955,10 +4664,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" @@ -4966,61 +4677,67 @@ 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.7" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.7.tgz#2473439021b57f1516c82f58be7275ad8ef1bb27" +parent-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" + integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== + dependencies: + callsites "^3.0.0" parse-asn1@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + version "5.1.4" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" + integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" -<<<<<<< HEAD -parse-code-context@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" -======= parse-cache-control@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" integrity sha1-juqz5U+laSD+Fro493+iGqzC104= ->>>>>>> dev-3.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" @@ -5030,6 +4747,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" @@ -5037,58 +4755,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" + 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" @@ -5097,12 +4818,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" @@ -5113,119 +4836,106 @@ 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" - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + 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" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= dependencies: - find-up "^1.0.0" + find-up "^2.1.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" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8= 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" -<<<<<<< HEAD - -prettier-plugin-solidity-refactor@^1.0.0-alpha.10: - version "1.0.0-alpha.10" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity-refactor/-/prettier-plugin-solidity-refactor-1.0.0-alpha.10.tgz#39c783d9bae100792a71dbd9b60277fbc5cfa31b" - dependencies: - emoji-regex "^7.0.1" - escape-string-regexp "^1.0.5" - extract-comments "^1.1.0" - prettier "^1.15.2" - solidity-parser-antlr "^0.3.1" - string-width "3.0.0" -======= ->>>>>>> dev-3.0.0 + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.15.3: - version "1.15.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" + version "1.16.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717" + integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g== 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.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - -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" - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise@^8.0.0: version "8.0.2" @@ -5237,6 +4947,7 @@ promise@^8.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" @@ -5246,34 +4957,36 @@ prompt@^1.0.0: 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" + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== dependencies: - loose-envify "^1.3.1" + loose-envify "^1.4.0" object-assign "^4.1.1" + react-is "^16.8.1" 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" -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - 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" @@ -5282,49 +4995,39 @@ 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.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" -<<<<<<< HEAD -======= + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== qs@^6.4.0: version "6.6.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2" integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA== ->>>>>>> dev-3.0.0 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.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" @@ -5333,12 +5036,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" @@ -5346,14 +5051,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" @@ -5363,6 +5071,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" @@ -5370,26 +5079,34 @@ rc@^1.2.7: strip-json-comments "~2.0.1" react-dom@^16.2.0: - version "16.6.3" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.6.3.tgz#8fa7ba6883c85211b8da2d0efeffc9d3825cccc0" + version "16.8.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.2.tgz#7c8a69545dd554d45d66442230ba04a6a0a3c3d3" + integrity sha512-cPGfgFfwi+VCZjk73buu14pYkYBR1b/SRMSYqkLDdhSEHnSwcuYTPu6/Bh6ZphJFIk80XLvbSe2azfcRzNF+Xg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.11.2" + scheduler "^0.13.2" + +react-is@^16.8.1: + version "16.8.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.2.tgz#09891d324cad1cb0c1f2d91f70a71a4bee34df0f" + integrity sha512-D+NxhSR2HUCjYky1q1DwpNUD44cDpUXzSmmFyC3ug1bClcU/iDNy0YNn1iwme28fn+NFhpA13IndOd42CrFb+Q== react@^16.2.0: - version "16.6.3" - resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c" + version "16.8.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.8.2.tgz#83064596feaa98d9c2857c4deae1848b542c9c0c" + integrity sha512-aB2ctx9uQ9vo09HVknqv3DGRpI7OIGJhCx3Bt0QqoRluEjHSaObJl+nG12GDdYH6sTgE7YiPJ6ZUyMx9kICdXw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.11.2" + scheduler "^0.13.2" 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" @@ -5397,6 +5114,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" @@ -5404,6 +5122,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" @@ -5412,6 +5131,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" @@ -5420,21 +5140,14 @@ 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" - 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.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: +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, 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" @@ -5444,48 +5157,41 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@~1.0.15: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - 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" @@ -5494,23 +5200,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@^2.0.0, regexpp@^2.0.1: +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" @@ -5519,34 +5229,41 @@ 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" @@ -5560,6 +5277,7 @@ req-cwd@^2.0.0: 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" @@ -5570,33 +5288,36 @@ req-from@^2.0.0: dependencies: resolve-from "^3.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" +request-promise-core@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" + integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== dependencies: - lodash "^4.13.1" + lodash "^4.17.11" request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" - integrity sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU= + version "1.0.7" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" + integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" + request-promise-core "1.1.2" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" request-promise@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.2.tgz#d1ea46d654a6ee4f8ee6a4fea1018c22911904b4" + version "4.2.4" + resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz#1c5ed0d71441e38ad58c7ce4ea4ea5b06d54b310" + integrity sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg== dependencies: bluebird "^3.5.0" - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" + request-promise-core "1.1.2" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" -request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.83.0, request@^2.85.0, request@^2.88.0: +request@^2.79.0, request@^2.81.0, request@^2.83.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" @@ -5622,169 +5343,152 @@ request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.83.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" - -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-jGStX9MNqxyXbiNE/+f3kqam30I= require-from-string@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 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" - -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -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-l/cXtp1IeE9fUmpsWqj/3aBVpNE= resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" -<<<<<<< HEAD -======= + integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c= resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= ->>>>>>> dev-3.0.0 + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 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" - 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" +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" + integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" 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" -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - 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.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" +rimraf@2, rimraf@2.6.3, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.6.1: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: - glob "^7.0.5" + 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" rlp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" + version "2.2.2" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.2.tgz#e6677b83cca9105371d930e01d8ffc1263139d05" + integrity sha512-Ng2kJEN731Sfv4ZAY2i0ytPMc0BbJKBsVNl0QZY8LxOWSwd+1xpg+fpSRfaMn0heHU447s6Kgy8qfHZR0XTyVw== dependencies: + bn.js "^4.11.1" 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" - -rxjs@^6.1.0: - version "6.3.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" +rxjs@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" + integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== 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" - -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" - dependencies: - events "^3.0.0" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 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" -scheduler@^0.11.2: - version "0.11.3" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.3.tgz#b5769b90cf8b1464f3f3cfcafe8e3cd7555a2d6b" +scheduler@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.2.tgz#969eaee2764a51d2e97b20a60963b2546beff8fa" + integrity sha512-qK5P8tHS7vdEMCW5IPyt8v9MJOHqTrOUgPXib7tqm9vh834ibBX5BNhwkplX/0iOzHW5sXyluehYfS9yrkz9+w== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -5792,14 +5496,12 @@ scheduler@^0.11.2: 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" - -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" @@ -5807,18 +5509,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" + version "3.6.2" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.6.2.tgz#da835061c833c74a12f75c73d2ec2e980f00dc1f" + integrity sha512-90nYt7yb0LmI4A2jJs1grglkTAXrBwxYAjP9bpeKjvJKOjG2fOeH/YI/lchDMIvjrOasd5QXwvV2jwN168xNng== dependencies: bindings "^1.2.1" bip66 "^1.1.3" @@ -5832,24 +5537,19 @@ 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" - "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" - -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== 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" @@ -5868,6 +5568,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" @@ -5877,6 +5578,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" @@ -5887,14 +5589,12 @@ 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" - -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-BF+XgtARrppoA93TgrJDkrPYkPc= 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" @@ -5904,27 +5604,27 @@ 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" is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - -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" @@ -5937,25 +5637,29 @@ sha1@^1.1.1: charenc ">= 0.0.1" crypt ">= 0.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, shelljs@^0.7.8: 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" @@ -5964,6 +5668,7 @@ shelljs@^0.7.4, shelljs@^0.7.8: 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" @@ -5972,14 +5677,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" @@ -5988,16 +5696,12 @@ 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" - -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - dependencies: - is-fullwidth-code-point "^2.0.0" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: ansi-styles "^3.2.0" astral-regex "^1.0.0" @@ -6006,6 +5710,7 @@ slice-ansi@^2.1.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" @@ -6014,12 +5719,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" @@ -6033,18 +5740,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.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" @@ -6056,6 +5767,7 @@ sol-merger@^0.1.2: solc@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.0.tgz#2deb2ae992acac3afb909f85c38d00f01dcb335e" + integrity sha512-mdLHDl9WeYrN+FIKcMc9PlPfnA9DG9ur5QpCDKcv6VC4RINAsTF4EMuXMZMKoQTvZhtLyJIVH/BZ+KU830Z8Xg== dependencies: fs-extra "^0.30.0" keccak "^1.0.2" @@ -6064,32 +5776,10 @@ solc@0.5.0: semver "^5.5.0" yargs "^11.0.0" -solc@^0.4.19, solc@^0.4.2: - version "0.4.25" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.25.tgz#06b8321f7112d95b4b903639b1138a4d292f5faa" - dependencies: - fs-extra "^0.30.0" - memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" - -solc@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.2.tgz#45d5d11569e41c2b2535f3a50fe0616ca771a347" - dependencies: - command-exists "^1.2.8" - fs-extra "^0.30.0" - keccak "^1.0.2" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - yargs "^11.0.0" - 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" @@ -6105,6 +5795,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" @@ -6114,20 +5805,15 @@ solidity-docgen@^0.1.0: react-dom "^16.2.0" shelljs "^0.8.1" -<<<<<<< HEAD -solidity-parser-antlr@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.3.2.tgz#1cf9d019280550a31299dc380e87a310dc4ca154" -======= solidity-parser-antlr@^0.2.10: version "0.2.15" resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.2.15.tgz#4be687a0a53da268c6a07398e0cfb3168896d610" integrity sha512-EzRI8/TR/ljTXkZAyAjb0w4G20wH2XM7pcNf87ifdV825AbUv7DkY7HmiZCTj6NeKtIx8Y1s0NZWPbj+JTp8Zw== ->>>>>>> dev-3.0.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" @@ -6136,27 +5822,31 @@ 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" + version "1.2.3" + resolved "https://registry.yarnpkg.com/solium/-/solium-1.2.3.tgz#88167ea6c8f7d1b68b59d3a6a78d563ca455ecdd" + integrity sha512-xMM/RcsUyZ3OTZWXwNXQGKdQdM2IqwqdRWJMUYFp6YBkd0Zzm4KTxyy0/KSazTaLk+OlmUE19OlSDiAN/GhhAQ== dependencies: ajv "^5.2.2" chokidar "^1.6.0" colors "^1.1.2" commander "^2.9.0" + diff "^3.5.0" eol "^0.9.1" js-string-escape "^1.0.1" lodash "^4.14.2" sol-digger "0.0.2" sol-explore "1.6.1" solium-plugin-security "0.1.1" - solparse "2.2.5" + solparse "2.2.8" text-table "^0.2.0" -solparse@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.5.tgz#72709c867cd6bfc50ec2325f4b81d2b3ea365d99" +solparse@2.2.8: + version "2.2.8" + resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" + integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== dependencies: mocha "^4.0.1" pegjs "^0.10.0" @@ -6165,14 +5855,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" @@ -6180,9 +5868,10 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.9, source-map-support@^0.5.3: +source-map-support@0.5.9: 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" @@ -6190,30 +5879,44 @@ 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-support@^0.5.3: + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" + integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + 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.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" @@ -6221,35 +5924,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.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2" + 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.15.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629" + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -6264,10 +5974,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" @@ -6275,54 +5987,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: +stealthy-require@^1.1.1: 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" -<<<<<<< HEAD - -string-width@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.0.0" -======= ->>>>>>> dev-3.0.0 + 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" @@ -6331,6 +6021,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" @@ -6338,120 +6029,113 @@ string-width@^1.0.1: string-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" + integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" strip-ansi "^5.0.0" -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" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.0" - function-bind "^1.0.2" - -string_decoder@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - 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" - 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@^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" @@ -6483,49 +6167,20 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" -table@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" - dependencies: - ajv "^6.5.3" - lodash "^4.17.10" - slice-ansi "1.0.0" - string-width "^2.1.1" - table@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" + integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== dependencies: ajv "^6.9.1" lodash "^4.17.11" slice-ansi "^2.1.0" string-width "^3.0.0" -tapable@^0.2.7: - version "0.2.9" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8" - -tape@^4.4.0, tape@^4.6.3: - version "4.9.1" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" - dependencies: - deep-equal "~1.0.1" - defined "~1.0.0" - for-each "~0.3.3" - function-bind "~1.1.1" - glob "~7.1.2" - has "~1.0.3" - inherits "~2.0.3" - minimist "~1.2.0" - object-inspect "~1.6.0" - resolve "~1.7.1" - resumer "~0.0.0" - string.prototype.trim "~1.1.2" - through "~2.3.8" - 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" @@ -6538,6 +6193,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" @@ -6548,6 +6204,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" @@ -6556,6 +6213,7 @@ 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" @@ -6568,6 +6226,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" @@ -6575,8 +6234,7 @@ 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" -<<<<<<< HEAD -======= + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= then-request@^6.0.0: version "6.0.0" @@ -6594,37 +6252,35 @@ then-request@^6.0.0: http-response-object "^3.0.1" promise "^8.0.0" qs "^6.4.0" ->>>>>>> dev-3.0.0 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: +through@^2.3.6, 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" @@ -6632,6 +6288,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" @@ -6639,33 +6296,34 @@ tingodb@^0.6.1: optionalDependencies: bson "^1.0.4" -tmp@0.0.33, tmp@^0.0.33: +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" @@ -6673,15 +6331,17 @@ 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.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" @@ -6689,6 +6349,7 @@ 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" @@ -6696,68 +6357,31 @@ 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-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.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" - web3 "^0.20.6" - web3-provider-engine "^13.8.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" +truffle-hdwallet-provider@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.4.tgz#f00ea8dbf8c243dad551f3f68813e09d159c8174" + integrity sha512-Z9LzA+SMH2kH52WJEcIoIbo+OY6aO4/uVCxqEIo0J+pJ4COuGLlLkM74pA6JAEf8Dr9o7sDtxMvuA7qbgjPhvQ== dependencies: - ethereumjs-wallet "^0.6.0" - web3 "^0.18.2" - web3-provider-engine "^8.4.0" + any-promise "^1.3.0" + bindings "^1.3.1" + websocket "^1.0.28" -<<<<<<< HEAD -truffle@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.0.tgz#2e4e2eedc5583ae38c7227585e5177d6360fbc6d" -======= truffle@^5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.4.tgz#fc68cb6a6a35b46a7ca69eca7b64d161b491db3d" integrity sha512-pZYFbU10Hb6PiTalJm+dB6s1qIZjE5qc0ux5fIgQ7Nj24zDrlYmOYruP3yhuqywwzr3PUHGPxr6hXuje0BFYoA== ->>>>>>> dev-3.0.0 dependencies: app-module-path "^2.2.0" mocha "^4.1.0" @@ -6767,34 +6391,36 @@ truffle@^5.0.4: tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + 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" @@ -6802,20 +6428,24 @@ 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.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" @@ -6824,56 +6454,41 @@ typedarray@^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" - 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" + version "1.3.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" + integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== dependencies: - buffer "^3.0.1" - through "^2.3.6" + buffer "^5.2.1" + through "^2.3.8" 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" @@ -6883,92 +6498,79 @@ 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" -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" - -utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= 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" @@ -6980,22 +6582,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" @@ -7003,36 +6605,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" @@ -7046,6 +6638,7 @@ watchr@~2.4.13: 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" @@ -7054,6 +6647,7 @@ web3-bzz@1.0.0-beta.35: 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.35" @@ -7062,6 +6656,7 @@ web3-core-helpers@1.0.0-beta.35: 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.35" @@ -7072,6 +6667,7 @@ web3-core-method@1.0.0-beta.35: 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" @@ -7079,6 +6675,7 @@ web3-core-promievent@1.0.0-beta.35: 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.35" @@ -7089,6 +6686,7 @@ web3-core-requestmanager@1.0.0-beta.35: 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" @@ -7097,6 +6695,7 @@ web3-core-subscriptions@1.0.0-beta.35: 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.35" web3-core-method "1.0.0-beta.35" @@ -7106,6 +6705,7 @@ web3-core@1.0.0-beta.35: 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: bn.js "4.11.6" underscore "1.8.3" @@ -7115,6 +6715,7 @@ web3-eth-abi@1.0.0-beta.35: 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" @@ -7130,6 +6731,7 @@ web3-eth-accounts@1.0.0-beta.35: 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.35" @@ -7143,6 +6745,7 @@ web3-eth-contract@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.35" @@ -7150,6 +6753,7 @@ web3-eth-iban@1.0.0-beta.35: 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.35" web3-core-helpers "1.0.0-beta.35" @@ -7160,6 +6764,7 @@ web3-eth-personal@1.0.0-beta.35: 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.35" @@ -7177,57 +6782,16 @@ web3-eth@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-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" - dependencies: - async "^2.5.0" - clone "^2.0.0" - eth-block-tracker "^2.2.2" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.1" - ethereumjs-vm "^2.0.2" - fetch-ponyfill "^4.0.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.67.0" - semaphore "^1.0.3" - solc "^0.4.2" - tape "^4.4.0" - xhr "^2.2.0" - xtend "^4.0.1" - -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" - dependencies: - async "^2.1.2" - clone "^2.0.0" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.0.2" - isomorphic-fetch "^2.2.0" - request "^2.67.0" - semaphore "^1.0.3" - solc "^0.4.2" - tape "^4.4.0" - web3 "^0.16.0" - xhr "^2.2.0" - xtend "^4.0.1" - 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" @@ -7235,6 +6799,7 @@ web3-providers-http@1.0.0-beta.35: 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" @@ -7243,6 +6808,7 @@ web3-providers-ipc@1.0.0-beta.35: 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.35" @@ -7251,6 +6817,7 @@ web3-providers-ws@1.0.0-beta.35: 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.35" web3-core-method "1.0.0-beta.35" @@ -7260,6 +6827,7 @@ web3-shh@1.0.0-beta.35: 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" @@ -7272,6 +6840,7 @@ web3-utils@1.0.0-beta.35: 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" @@ -7282,16 +6851,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" @@ -7302,6 +6862,7 @@ web3@0.20.6: 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" @@ -7311,18 +6872,10 @@ web3@1.0.0-beta.35: web3-shh "1.0.0-beta.35" web3-utils "1.0.0-beta.35" -web3@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" - dependencies: - bignumber.js "git+https://github.com/debris/bignumber.js#master" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xmlhttprequest "*" - -web3@^0.18.2, web3@^0.18.4: +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" @@ -7330,49 +6883,15 @@ web3@^0.18.2, web3@^0.18.4: xhr2 "*" xmlhttprequest "*" -web3@^0.20.6: - version "0.20.7" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.7.tgz#1605e6d81399ed6f85a471a4f3da0c8be57df2f7" - dependencies: - bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" - crypto-js "^3.1.4" - utf8 "^2.1.1" - 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" +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: - 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" + 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" @@ -7383,41 +6902,39 @@ webpack@^3.0.0: typedarray-to-buffer "^3.1.2" yaeti "^0.0.6" -whatwg-fetch@>=0.10.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - 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 "https://registry.yarnpkg.com/winston/-/winston-2.1.1.tgz#3c9349d196207fd1bdff9d4bc43ef72510e3a12e" + integrity sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4= dependencies: async "~1.0.0" colors "1.0.x" @@ -7430,6 +6947,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" @@ -7438,21 +6956,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" @@ -7460,16 +6977,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" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== 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" @@ -7478,12 +6998,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" @@ -7493,19 +7015,22 @@ xhr-request@^1.0.1: url-set-query "^1.0.0" xhr "^2.0.4" -xhr2-cookies@1.1.0, xhr2-cookies@^1.1.0: +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@*: 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: +xhr@^2.0.4, 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" @@ -7515,69 +7040,69 @@ 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: +xmlhttprequest@*: 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: +xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - dependencies: - object-keys "~0.4.0" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= 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" -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@11.1.0, 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" @@ -7595,6 +7120,7 @@ yargs@11.1.0, yargs@^11.0.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" @@ -7609,9 +7135,10 @@ yargs@^10.0.3: y18n "^3.2.1" yargs-parser "^8.1.0" -yargs@^4.6.0, yargs@^4.7.1: +yargs@^4.6.0: 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" @@ -7628,36 +7155,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 f6a1caaf6caac86bbf2f97e5dc0dd41275e71b4f Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 13:08:31 +0530 Subject: [PATCH 115/119] Added missing depencency --- package.json | 25 +- yarn.lock | 853 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 818 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index 4c4229b4b..1f2166163 100644 --- a/package.json +++ b/package.json @@ -58,9 +58,17 @@ "homepage": "https://github.com/PolymathNetwork/polymath-core#readme", "dependencies": { "truffle": "^5.0.4", - "truffle-hdwallet-provider": "^1.0.4" + "truffle-hdwallet-provider": "^1.0.4", + "web3-provider-engine": "^14.1.0" }, "devDependencies": { + "babel-polyfill": "6.26.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-2": "6.24.1", + "babel-preset-stage-3": "6.24.1", + "babel-register": "6.26.0", + "chalk": "^2.4.2", + "coveralls": "^3.0.1", "eslint": "^5.8.0", "eslint-config-standard": "^12.0.0", "eslint-plugin-import": "^2.10.0", @@ -70,26 +78,19 @@ "eth-gas-reporter": "^0.1.12", "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", + "fs": "0.0.2", "ganache-cli": "^6.2.4", "mocha-junit-reporter": "^1.18.0", "openzeppelin-solidity": "2.1.2", "prettier": "^1.15.3", + "prompt": "^1.0.0", + "request": "^2.88.0", + "request-promise": "^4.2.2", "sol-merger": "^0.1.2", "solidity-coverage": "^0.5.11", "solidity-docgen": "^0.1.0", "solium": "^1.1.6", "table": "^5.2.3", - "babel-polyfill": "6.26.0", - "babel-preset-es2015": "6.24.1", - "babel-preset-stage-2": "6.24.1", - "babel-preset-stage-3": "6.24.1", - "babel-register": "6.26.0", - "chalk": "^2.4.2", - "coveralls": "^3.0.1", - "fs": "0.0.2", - "prompt": "^1.0.0", - "request": "^2.88.0", - "request-promise": "^4.2.2", "web3": "1.0.0-beta.35" }, "greenkeeper": { diff --git a/yarn.lock b/yarn.lock index 6206a8dfb..cba138ce2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -69,6 +69,20 @@ abi-decoder@^1.0.8: dependencies: web3 "^0.18.4" +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" @@ -268,17 +282,30 @@ async-each@^1.0.0: 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@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c": + version "0.2.3" + resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" + dependencies: + async "^2.4.0" + 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.5.2: +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.4.1, async@^2.5.0: +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.4.1, async@^2.5.0: version "2.6.2" resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== @@ -324,7 +351,7 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@^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== @@ -558,7 +585,7 @@ babel-plugin-transform-async-generator-functions@^6.24.1: babel-plugin-syntax-async-generators "^6.5.0" babel-runtime "^6.22.0" -babel-plugin-transform-async-to-generator@^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= @@ -602,7 +629,7 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoping@^6.24.1: +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= @@ -613,7 +640,7 @@ babel-plugin-transform-es2015-block-scoping@^6.24.1: babel-types "^6.26.0" lodash "^4.17.4" -babel-plugin-transform-es2015-classes@^6.24.1: +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= @@ -628,7 +655,7 @@ babel-plugin-transform-es2015-classes@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-computed-properties@^6.24.1: +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= @@ -636,14 +663,14 @@ babel-plugin-transform-es2015-computed-properties@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-destructuring@^6.22.0: +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.24.1: +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= @@ -651,14 +678,14 @@ babel-plugin-transform-es2015-duplicate-keys@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-plugin-transform-es2015-for-of@^6.22.0: +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.24.1: +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= @@ -674,7 +701,7 @@ babel-plugin-transform-es2015-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.24.1: +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= @@ -683,7 +710,7 @@ babel-plugin-transform-es2015-modules-amd@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@^6.24.1: +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== @@ -693,7 +720,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.24.1: babel-template "^6.26.0" babel-types "^6.26.0" -babel-plugin-transform-es2015-modules-systemjs@^6.24.1: +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= @@ -702,7 +729,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-umd@^6.24.1: +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= @@ -711,7 +738,7 @@ babel-plugin-transform-es2015-modules-umd@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-object-super@^6.24.1: +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= @@ -719,7 +746,7 @@ babel-plugin-transform-es2015-object-super@^6.24.1: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.24.1: +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= @@ -731,7 +758,7 @@ babel-plugin-transform-es2015-parameters@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-shorthand-properties@^6.24.1: +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= @@ -746,7 +773,7 @@ babel-plugin-transform-es2015-spread@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.24.1: +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= @@ -762,14 +789,14 @@ babel-plugin-transform-es2015-template-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-typeof-symbol@^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.24.1: +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= @@ -778,7 +805,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1: babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.24.1: +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= @@ -795,7 +822,7 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.26.0" -babel-plugin-transform-regenerator@^6.24.1: +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= @@ -819,6 +846,42 @@ babel-polyfill@6.26.0: core-js "^2.5.0" regenerator-runtime "^0.10.5" +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" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.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" @@ -927,11 +990,26 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: lodash "^4.17.4" to-fast-properties "^1.0.3" +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" + 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== +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= + dependencies: + precond "0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1068,7 +1146,7 @@ bn.js@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.1, 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.1, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.11.8, 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== @@ -1213,6 +1291,14 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.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" + bs58@=4.0.1, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -1328,6 +1414,11 @@ caminte@0.3.7: bluebird "^3.4.6" uuid "^3.0.1" +caniuse-lite@^1.0.30000844: + version "1.0.30000938" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000938.tgz#b64bf1427438df40183fce910fe24e34feda7a3f" + integrity sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -1363,6 +1454,13 @@ chardet@^0.7.0: 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" @@ -1454,7 +1552,7 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" -clone@2.x: +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= @@ -1548,7 +1646,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.4.6, concat-stream@^1.6.0: +concat-stream@^1.4.6, concat-stream@^1.5.1, 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== @@ -1674,6 +1772,14 @@ cron-parser@^2.7.3: is-nan "^1.2.1" moment-timezone "^0.5.23" +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.3.tgz#e8a0b3c54598136e037f8650f8e823ccdfac198e" + integrity sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw== + dependencies: + node-fetch "2.1.2" + whatwg-fetch "2.0.4" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -1858,6 +1964,11 @@ deep-equal@~0.2.1: 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" @@ -1868,7 +1979,14 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -define-properties@^1.1.1: +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== @@ -1897,6 +2015,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +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" @@ -2028,6 +2151,11 @@ ee-first@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.113" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9" + integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g== + elliptic@=6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -2074,7 +2202,14 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.0.0: +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, end-of-stream@^1.1.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== @@ -2093,6 +2228,13 @@ errlop@^1.1.1: 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" @@ -2100,6 +2242,27 @@ error-ex@^1.2.0: 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" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + +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" + is-symbol "^1.0.2" + 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.47" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.47.tgz#d24232e1380daad5449a817be19bde9729024a11" @@ -2338,6 +2501,33 @@ etag@~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" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + eth-gas-reporter@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.1.12.tgz#6b761e05c33ae85be47840dd07468ab51d473dd8" @@ -2356,6 +2546,36 @@ eth-gas-reporter@^0.1.12: solidity-parser-antlr "^0.2.10" sync-request "^6.0.0" +eth-json-rpc-infura@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.0.tgz#62c3f516b51351038c32a548704467cec113ca8f" + integrity sha512-FLcpdxPRVBCUc7yoE+wHGvyYg2lATedP+/q7PsKvaSzQpJbgTG4ZjLnyrLanxDr6M1k/dSNa6V5QnILwjUKJcw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + tape "^4.8.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + 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" @@ -2395,6 +2615,41 @@ eth-lightwallet@^3.0.1: tweetnacl "0.13.2" web3 "0.20.2" +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + 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" + +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" + +eth-tx-summary@^3.1.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.3.tgz#a52d7215616888e012fbc083b3eacd28f3e64764" + integrity sha512-1gZpA5fKarJOVSb5OUlPnhDQuIazqAkI61zlVvf5LdG47nEgw+/qhyZnuj3CUdE/TLTKuRzPLeyXLjaB4qWTRQ== + dependencies: + async "^2.1.2" + bn.js "^4.11.8" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "2.3.4" + through2 "^2.0.3" + treeify "^1.0.1" + web3-provider-engine "^13.3.2" + ethereum-bridge@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ethereum-bridge/-/ethereum-bridge-0.6.1.tgz#53c93ed7c0e21752a91e5f089a5997e1d6fea228" @@ -2426,6 +2681,11 @@ ethereum-bridge@^0.6.1: web3 "0.19.1" winston "^2.3.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" @@ -2447,6 +2707,49 @@ ethereumjs-abi@^0.6.5: bn.js "^4.10.0" ethereumjs-util "^5.0.0" +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.6" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215" + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^5.0.0" + +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.4.1, ethereumjs-block@^1.6.0, 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" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.0.tgz#8c6c3ab4a5eff0a16d9785fbeedbe643f4dbcbef" + integrity sha512-Ye+uG/L2wrp364Zihdlr/GfC3ft+zG8PdHcRtsBFNNH1CkOhxOwdB8friBU85n89uRZ9eIMAywCq0F4CwT1wAw== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.1.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-common@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.1.0.tgz#5ec9086c314d619d8f05e79a0525829fcb0e93cb" + integrity sha512-LUmYkKV/HcZbWRyu3OU9YOevsH3VJDXtI6kEd8VZweQec+JjDGKCmAVKUyzhYUHqxRJu7JNALZ3A/b3NXOP6tA== + 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" @@ -2454,7 +2757,7 @@ ethereumjs-testrpc-sc@6.1.6: dependencies: source-map-support "^0.5.3" -ethereumjs-tx@^1.3.1, ethereumjs-tx@^1.3.3: +ethereumjs-tx@^1.1.1, 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== @@ -2473,7 +2776,7 @@ ethereumjs-util@^4.3.0: rlp "^2.0.0" secp256k1 "^3.0.1" -ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.2.0: +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, 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== @@ -2486,6 +2789,53 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1, ethereumjs-util@^5.2.0: safe-buffer "^5.1.1" secp256k1 "^3.0.1" +ethereumjs-util@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" + integrity sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q== + 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.3.4: + version "2.3.4" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz#f635d7cb047571a1840a6e9a74d29de4488f8ad6" + integrity sha512-Y4SlzNDqxrCO58jhp98HdnZVdjOqB+HC0hoU+N/DEp1aU+hFkRX/nru5F7/HkQRPIlA6aJlQp/xIA6xZs1kspw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereum-common "0.2.0" + ethereumjs-account "^2.0.3" + ethereumjs-block "~1.7.0" + ethereumjs-util "^5.1.3" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.1.2" + rustbn.js "~0.1.1" + safe-buffer "^5.1.1" + +ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -2494,7 +2844,7 @@ ethjs-unit@0.1.6: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@^0.1.3: +ethjs-util@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== @@ -2515,6 +2865,11 @@ eventemitter3@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" @@ -2678,6 +3033,13 @@ eyes@0.1.x: 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" @@ -2705,6 +3067,13 @@ fd-slicer@~1.1.0: 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" @@ -2807,7 +3176,7 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== -for-each@^0.3.2: +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== @@ -2935,7 +3304,7 @@ fstream@^1.0.2, fstream@^1.0.8: mkdirp ">=0.5 0" rimraf "2" -function-bind@^1.1.1: +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== @@ -3041,7 +3410,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.1.2, glob@^7.1.3: +glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -3173,6 +3542,11 @@ has-symbol-support-x@^1.4.1: 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" @@ -3216,7 +3590,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.3: +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== @@ -3333,7 +3707,7 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.4.24, iconv-lite@^0.4.4: +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== @@ -3375,6 +3749,11 @@ ignorepatterns@^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= + import-fresh@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" @@ -3396,7 +3775,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: +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= @@ -3483,7 +3862,7 @@ is-buffer@^1.1.5, is-buffer@~1.1.1: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.3: +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== @@ -3502,6 +3881,11 @@ is-data-descriptor@^1.0.0: 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" @@ -3556,6 +3940,11 @@ is-finite@^1.0.0: 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" @@ -3648,16 +4037,30 @@ is-promise@^2.1, is-promise@^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.1.0: +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" @@ -3673,6 +4076,11 @@ is-windows@^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" @@ -3776,6 +4184,30 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +json-rpc-engine@^3.4.0, 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" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +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" @@ -3796,6 +4228,13 @@ json-stable-stringify-without-jsonify@^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" @@ -3827,6 +4266,11 @@ jsonfile@^4.0.0: 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" @@ -3898,6 +4342,56 @@ lcov-parse@^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" + readable-stream "^1.0.33" + xtend "^4.0.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" + +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" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -3987,6 +4481,11 @@ lru-queue@0.1: 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" @@ -4055,6 +4554,18 @@ mem@^1.1.0: 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" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + memoizee@^0.4.14: version "0.4.14" resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" @@ -4079,6 +4590,20 @@ merge-descriptors@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, merkle-patricia-tree@^2.3.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" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + messageformat@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-0.3.1.tgz#e58fff8245e9b3971799e5b43db58b3e9417f5a2" @@ -4197,7 +4722,7 @@ minimist@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, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= @@ -4436,6 +4961,19 @@ node-cache@^4.1.1: clone "2.x" lodash "4.x" +node-fetch@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" + integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= + +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-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" @@ -4541,7 +5079,7 @@ oauth-sign@~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.1, object-assign@^4.1.0, object-assign@^4.1.1: +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= @@ -4555,11 +5093,21 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.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.1.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== +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" @@ -4897,6 +5445,11 @@ pragma-singleton@1.0.3: resolved "https://registry.yarnpkg.com/pragma-singleton/-/pragma-singleton-1.0.3.tgz#6894317bb8d47157e59de2a4a009db7e6f63e30e" integrity sha1-aJQxe7jUcVflneKkoAnbfm9j4w4= +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -4937,6 +5490,14 @@ progress@^2.0.0: 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" + promise@^8.0.0: version "8.0.2" resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.2.tgz#9dcd0672192c589477d56891271bdc27547ae9f0" @@ -4973,6 +5534,11 @@ proxy-addr@~2.0.4: forwarded "~0.1.2" ipaddr.js "1.8.0" +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" @@ -5144,7 +5710,17 @@ read@1.0.x: dependencies: mute-stream "~0.0.4" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5: +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.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.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== @@ -5157,6 +5733,16 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +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" + isarray "0.0.1" + string_decoder "~0.10.x" + readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -5314,7 +5900,7 @@ request-promise@^4.2.2: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.79.0, request@^2.81.0, request@^2.83.0, request@^2.85.0, request@^2.88.0: +request@^2.67.0, request@^2.79.0, request@^2.81.0, request@^2.83.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== @@ -5345,6 +5931,11 @@ require-directory@^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-from-string@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" @@ -5380,7 +5971,7 @@ resolve@1.1.x: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.5.0, resolve@^1.8.1, resolve@^1.9.0, resolve@~1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== @@ -5395,6 +5986,13 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +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" @@ -5435,6 +6033,16 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +rustbn.js@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.1.2.tgz#979fa0f9562216dd667c9d2cd179ae5d13830eff" + integrity sha512-bAkNqSHYdJdFsBC7Z11JgzYktL31HIpB2o70jZcGiL1U1TVtPyvaVhDrGWwS8uZtaqwW2k6NOPGZCqW/Dgh5Lg== + +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.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" @@ -5447,6 +6055,13 @@ 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/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" @@ -5541,11 +6156,21 @@ seek-bzip@^1.0.5: 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" @@ -5591,6 +6216,11 @@ set-blocking@^2.0.0, set-blocking@~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" @@ -5776,6 +6406,17 @@ solc@0.5.0: semver "^5.5.0" yargs "^11.0.0" +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" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + solidity-coverage@^0.5.11: version "0.5.11" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" @@ -6035,6 +6676,20 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.0.0" +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@~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" @@ -6177,6 +6832,25 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" +tape@^4.4.0, tape@^4.6.3, tape@^4.8.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.10.1.tgz#f73be60888dcb120f08b57f947af65a829506a5f" + integrity sha512-G0DywYV1jQeY3axeYnXUOt6ktnxS9OPJh97FGR3nrua8lhWi1zPflLxcAHavZ7Jf3qUfY7cxcVIVFa4mY2IY1w== + dependencies: + deep-equal "~1.0.1" + defined "~1.0.0" + for-each "~0.3.3" + function-bind "~1.1.1" + glob "~7.1.3" + has "~1.0.3" + inherits "~2.0.3" + minimist "~1.2.0" + object-inspect "~1.6.0" + resolve "~1.10.0" + resumer "~0.0.0" + string.prototype.trim "~1.1.2" + through "~2.3.8" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -6267,7 +6941,15 @@ thenify-all@^1.0.0, thenify-all@^1.6.0: dependencies: any-promise "^1.0.0" -through@^2.3.6, through@^2.3.8: +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@^2.3.6, through@^2.3.8, 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= @@ -6359,6 +7041,11 @@ tree-kill@^1.2.0: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== +treeify@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" + integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -6788,6 +7475,57 @@ web3-net@1.0.0-beta.35: web3-core-method "1.0.0-beta.35" web3-utils "1.0.0-beta.35" +web3-provider-engine@^13.3.2: + 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" + eth-block-tracker "^2.2.2" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.1" + ethereumjs-vm "^2.0.2" + fetch-ponyfill "^4.0.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.67.0" + semaphore "^1.0.3" + solc "^0.4.2" + tape "^4.4.0" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-provider-engine@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.1.0.tgz#91590020f8b8c1b65846321310cbfdb039090fc6" + integrity sha512-vGZtqhSUzGTiMGhJXNnB/aRDlrPZLhLnBZ2NPArkZtr8XSrwg9m08tw4+PuWg5za0TJuoE/vuPQc501HddZZWw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + 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" @@ -6902,6 +7640,11 @@ websocket@^1.0.28: typedarray-to-buffer "^3.1.2" yaeti "^0.0.6" +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" @@ -6995,6 +7738,13 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" +ws@^5.1.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== + dependencies: + async-limiter "~1.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" @@ -7027,7 +7777,7 @@ xhr2@*: resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" integrity sha1-f4dliEdxbbUCYyOBL4GMras4el8= -xhr@^2.0.4, xhr@^2.3.3: +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== @@ -7052,11 +7802,18 @@ xregexp@^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.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: 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" @@ -7135,7 +7892,7 @@ yargs@^10.0.3: y18n "^3.2.1" yargs-parser "^8.1.0" -yargs@^4.6.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= From d59ee9da3a422721285ebc8e7bd1b51f82c7e4a6 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 13:09:36 +0530 Subject: [PATCH 116/119] Removed pify --- test/helpers/time.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/helpers/time.js b/test/helpers/time.js index f30f73409..2d665219c 100644 --- a/test/helpers/time.js +++ b/test/helpers/time.js @@ -2,8 +2,6 @@ // aren’t included within the original RPC specification. // See https://github.com/ethereumjs/testrpc#implemented-methods -const pify = require('pify'); - async function advanceBlock() { return new Promise((resolve, reject) => { web3.currentProvider.send({ From 0db89f272f6f317cb9b5f5b0b6c0918dd9be1936 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 13:43:15 +0530 Subject: [PATCH 117/119] Updated ganache-cli --- package.json | 2 +- yarn.lock | 14 +++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 1f2166163..b225e316d 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", "fs": "0.0.2", - "ganache-cli": "^6.2.4", + "ganache-cli": "^6.3.0", "mocha-junit-reporter": "^1.18.0", "openzeppelin-solidity": "2.1.2", "prettier": "^1.15.3", diff --git a/yarn.lock b/yarn.lock index cba138ce2..1591bc5ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -289,7 +289,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: @@ -2699,15 +2699,7 @@ ethereumjs-abi@0.6.4: bn.js "^4.10.0" ethereumjs-util "^4.3.0" -ethereumjs-abi@^0.6.5: - version "0.6.6" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.6.tgz#f8ba3413a98478173f5a00f7f1316819db1d09ec" - integrity sha512-w8KubDsA/+OAuqtIR9RGsMcoZ5nhM8vxwjJAJvEIY+clhxA3BHoLG3+ClYQaQhD0n3mlDt3U5rBrmSVJvI3c8A== - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^5.0.0" - -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": +ethereumjs-abi@^0.6.5, "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": version "0.6.6" resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#d84a96796079c8595a0c78accd1e7709f2277215" dependencies: @@ -3314,7 +3306,7 @@ 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.2.4: +ganache-cli@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.3.0.tgz#574f9d35aaec8da6e01c2be49db8fe73129eb561" integrity sha512-8SyzfX2ipRVBx1fBZLg3j8I3E334U3Vazk5mEpYcWqnIjC2ace6jtOXHG4aTuAvSz3+HzQ8p8pRjOJxdDZ2pnQ== From 31d12c0931b095e883125156793685adc94bf3cd Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 14:58:19 +0530 Subject: [PATCH 118/119] fix ganache-cli version --- package.json | 5 +++-- test/o_security_token.js | 2 +- yarn.lock | 42 +++++++++++++++------------------------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index b225e316d..3cc06302e 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "ethereum-bridge": "^0.6.1", "ethereumjs-abi": "^0.6.5", "fs": "0.0.2", - "ganache-cli": "^6.3.0", + "ganache-cli": "6.1.8", "mocha-junit-reporter": "^1.18.0", "openzeppelin-solidity": "2.1.2", "prettier": "^1.15.3", @@ -97,7 +97,8 @@ "ignore": [ "openzeppelin-solidity", "web3", - "truffle-hdwallet-provider" + "truffle-hdwallet-provider", + "ganache-cli" ] } } diff --git a/test/o_security_token.js b/test/o_security_token.js index 2d0808112..069dcf3fe 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -1332,7 +1332,7 @@ contract("SecurityToken", async (accounts) => { `) assert.equal( - (await stGetter.controller.call()).substring(0, 3), + (await stGetter.controller.call()).substring(0, 4), await readStorage(I_SecurityToken.address, 7) ); diff --git a/yarn.lock b/yarn.lock index 1591bc5ba..91971f5ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1146,7 +1146,7 @@ bn.js@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.1, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0: +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.1, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.11.8, 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== @@ -3306,14 +3306,12 @@ 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.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.3.0.tgz#574f9d35aaec8da6e01c2be49db8fe73129eb561" - integrity sha512-8SyzfX2ipRVBx1fBZLg3j8I3E334U3Vazk5mEpYcWqnIjC2ace6jtOXHG4aTuAvSz3+HzQ8p8pRjOJxdDZ2pnQ== +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: - bn.js "4.11.8" - source-map-support "0.5.9" - yargs "11.1.0" + source-map-support "^0.5.3" gauge@~2.7.3: version "2.7.4" @@ -6501,14 +6499,6 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.9: - 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" @@ -7848,10 +7838,10 @@ yargs-parser@^9.0.2: dependencies: camelcase "^4.1.0" -yargs@11.1.0, 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== +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" @@ -7864,12 +7854,12 @@ yargs@11.1.0, 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@^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== +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" @@ -7882,7 +7872,7 @@ 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@^4.6.0, yargs@^4.7.1: version "4.8.1" From 2613f60a23240b1770e4a5f9869278d232f6d739 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 19 Feb 2019 15:57:38 +0530 Subject: [PATCH 119/119] changes to accomodate different web3 versions --- test/o_security_token.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/o_security_token.js b/test/o_security_token.js index 069dcf3fe..24f29d4e6 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -1330,10 +1330,14 @@ contract("SecurityToken", async (accounts) => { Controller address from the contract: ${await stGetter.controller.call()} Controller address from the storage: ${await readStorage(I_SecurityToken.address, 7)} `) - - assert.equal( - (await stGetter.controller.call()).substring(0, 4), - await readStorage(I_SecurityToken.address, 7) + // Different versions of web3 behave differently :/ + assert.oneOf( + await readStorage(I_SecurityToken.address, 7), + [ + (await stGetter.controller.call()).substring(0, 4), + (await stGetter.controller.call()).substring(0, 3), + await stGetter.controller.call() + ] ); console.log(`