From 6ec7a7aac2047df904f304128fc98c49d39ec452 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 7 Feb 2019 13:03:04 +0530 Subject: [PATCH 01/24] wip --- contracts/modules/STO/USDTieredSTO.sol | 95 ++++++++++++----------- contracts/storage/USDTieredSTOStorage.sol | 19 +---- 2 files changed, 55 insertions(+), 59 deletions(-) diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index bd64aaca6..d4845225b 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -272,23 +272,23 @@ 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 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 @@ -299,35 +299,32 @@ 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 - */ - 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 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) { + // // + // // + // // Fetch list from Datastore then do the magic + // // + // // + // 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) @@ -489,8 +486,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 +565,16 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { } } + function _isAccredited(address _investor) internal view returns(bool) { + IDataStore dataStore = IDataStore(getDataStore()); + uint256 whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); + return (uint8(whitelistData) > 0); + } + + function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1, _key2))); + } + ///////////// // Getters // ///////////// diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index 267df4f58..0b97d70b2 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 WHITELIST = "WHITELIST"; + ///////////// // 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) 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; From 48538a35a3dff22933168af8813de2e16a4487bc Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 12 Feb 2019 11:07:19 +0530 Subject: [PATCH 02/24] wip --- contracts/datastore/DataStore.sol | 131 +++++---- contracts/libraries/VersionUtils.sol | 29 +- .../GeneralTransferManager.sol | 249 +++++++++++++----- .../storage/GeneralTransferManagerStorage.sol | 12 +- 4 files changed, 280 insertions(+), 141 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 3c68aac97..5f6b03944 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -12,7 +12,6 @@ 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() { @@ -56,26 +55,26 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _data Data to be stored against the key */ function setUint256(bytes32 _key, uint256 _data) external onlyAuthorized { - _setData(_key, _data); + _setData(_key, _data, false); } function setBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { - _setData(_key, _data); + _setData(_key, _data, false); } function setAddress(bytes32 _key, address _data) external onlyAuthorized { - _setData(_key, _data); + _setData(_key, _data, false); } - function setString(bytes32 _key, string calldata _data) external onlyAuthorized { - _setData(_key, _data); + function setBool(bytes32 _key, bool _data) external onlyAuthorized { + _setData(_key, _data, false); } - function setBytes(bytes32 _key, bytes calldata _data) external onlyAuthorized { + function setString(bytes32 _key, string calldata _data) external onlyAuthorized { _setData(_key, _data); } - function setBool(bytes32 _key, bool _data) external onlyAuthorized { + function setBytes(bytes32 _key, bytes calldata _data) external onlyAuthorized { _setData(_key, _data); } @@ -106,19 +105,19 @@ contract DataStore is DataStoreStorage, IDataStore { * @param _data Element to push into the array */ function insertUint256(bytes32 _key, uint256 _data) external onlyAuthorized { - _insertData(_key, _data); + _setData(_key, _data, true); } function insertBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { - _insertData(_key, _data); + _setData(_key, _data, true); } function insertAddress(bytes32 _key, address _data) external onlyAuthorized { - _insertData(_key, _data); + _setData(_key, _data, true); } function insertBool(bytes32 _key, bool _data) external onlyAuthorized { - _insertData(_key, _data); + _setData(_key, _data, true); } /** @@ -150,25 +149,25 @@ contract DataStore is DataStoreStorage, IDataStore { */ 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]); + _setData(_keys[i], _data[i], false); } } 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]); + _setData(_keys[i], _data[i], false); } } 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]); + _setData(_keys[i], _data[i], false); } } 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]); + _setData(_keys[i], _data[i], false); } } @@ -179,25 +178,25 @@ contract DataStore is DataStoreStorage, IDataStore { */ 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]); + _setData(_keys[i], _data[i], true); } } 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]); + _setData(_keys[i], _data[i], true); } } 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]); + _setData(_keys[i], _data[i], true); } } 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]); + _setData(_keys[i], _data[i], true); } } @@ -273,16 +272,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 _setData(bytes32 _key, bytes32 _data) internal validKey(_key) { - bytes32Data[_key] = _data; + 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 _setData(bytes32 _key, address _data) internal validKey(_key) { - addressData[_key] = _data; + 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, address _data, bool _insert) internal validKey(_key) { + if (_insert) + addressArrayData[_key].push(_data); + else + 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 +336,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 +352,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/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 8375cde68..17774983a 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -110,19 +110,34 @@ 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) { + 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); + 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); + } + + /** + * @notice Used to packed the KYC data + */ + function packInvestorData(uint240 _a, uint8 _b, uint8 _c) internal pure returns(uint256) { + return (uint256(_a) << 16) | (uint256(_b) << 8) | uint256(_c); + } + + /** + * @notice Used to convert packed data into KYC data + * @param _packedVersion Packed data + */ + function unpackInvestorData(uint256 _packedVersion) internal pure returns(uint240 limit, uint8 added, uint8 accredited) { + limit = uint240(_packedVersion >> 16); added = uint8(_packedVersion >> 8); accredited = uint8(_packedVersion); } diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 0139291ef..bd747310e 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -34,15 +34,20 @@ 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 ModifyInvestorData( + address indexed _investor, + uint256 nonAccreditedLimitUSDOverride, + bool canBuyFromSTO, + bool isAccredited ); /** @@ -158,7 +163,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 +171,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 @@ -177,9 +181,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage (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 ((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,68 +201,109 @@ 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(_getKey(INVESTORS), _investor); + } + uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), uint8(1)); + dataStore.setUint256(_getKey(KYCDATA, _investor), _data); + emit ModifyKYCData(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime); } /** - * @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 + */ + 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 data. + * @param _investor is the address to whitelist + * @param _nonAccreditedLimitUSDOverride Overrides default non accredited purchase limit for the investor. * @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 modifyInvestorData( + address _investor, + uint256 _nonAccreditedLimitUSDOverride, + bool _canBuyFromSTO, + bool _isAccredited + ) + public + withPerm(WHITELIST) + { + _modifyInvestorData(_investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited); + } + + + function _modifyInvestorData(address _investor, uint256 _nonAccreditedLimitUSDOverride, bool _canBuyFromSTO, bool _isAccredited) 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(_getKey(INVESTORS), _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(KYCDATA, _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); + uint256 _data = VersionUtils.packInvestorData(uint240(_nonAccreditedLimitUSDOverride), canBuyFromSTO, isAccredited); + dataStore.setUint256(_getKey(INVESTORDATA, _investor), _data); + emit ModifyInvestorData(_investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited); } /** - * @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 + * @notice Used to modify investor data. + * @param _investors List of the addresses to modify data about. + * @param _nonAccreditedLimitUSDOverride Overrides default non accredited purchase limit for the investor. * @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( + function modifyInvestorDataMulti( address[] memory _investors, - uint256[] memory _fromTimes, - uint256[] memory _toTimes, - uint256[] memory _expiryTimes, + uint256[] memory _nonAccreditedLimitUSDOverride, bool[] memory _canBuyFromSTO, bool[] memory _isAccredited ) @@ -266,24 +311,20 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage withPerm(WHITELIST) { require( - _investors.length == _fromTimes.length && - _fromTimes.length == _toTimes.length && - _toTimes.length == _expiryTimes.length && - _canBuyFromSTO.length == _toTimes.length && + _investors.length == _nonAccreditedLimitUSDOverride.length && + _nonAccreditedLimitUSDOverride.length == _canBuyFromSTO.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], _isAccredited[i]); + _modifyInvestorData(_investors[i], _nonAccreditedLimitUSDOverride[i], _canBuyFromSTO[i], _isAccredited[i]); } } /** * @notice Adds or removes addresses from the whitelist - can be called by anyone with a valid signature * @param _investor is the address to whitelist - * @param _fromTime is the moment when the sale lockup period ends and the investor can freely sell his tokens - * @param _toTime is the moment when the purchase lockup period ends and the investor can freely purchase tokens from others - * @param _expiryTime is the moment till investors KYC will be validated. After that investor need to do re-KYC + * @param _nonAccreditedLimitUSDOverride Overrides default non accredited purchase limit for the investor. * @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 @@ -291,11 +332,9 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage * @param _nonce nonce of signature (avoid replay attack) * @param _signature issuer signature */ - function modifyWhitelistSigned( + function modifyInvestorDataSigned( address _investor, - uint256 _fromTime, - uint256 _toTime, - uint256 _expiryTime, + uint256 _nonAccreditedLimitUSDOverride, bool _canBuyFromSTO, bool _isAccredited, uint256 _validFrom, @@ -312,10 +351,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, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited, _validFrom, _validTo, _nonce) ); _checkSig(hash, _signature); - _modifyWhitelist(_investor, _fromTime, _toTime, _expiryTime, _canBuyFromSTO, _isAccredited); + _modifyInvestorData(_investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited); } /** @@ -371,51 +410,121 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function _getValues(address _investor, IDataStore dataStore) internal view returns( + function _getKey(bytes32 _key1) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1))); + } + + 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(KYCDATA, _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 _getInvestorValues(address _investor, IDataStore dataStore) internal view returns( + uint240 _nonAccreditedLimitUSDOverride, + uint8 _canBuyFromSTO, + uint8 _isAccredited + ) + { + uint256 data = dataStore.getUint256(_getKey(INVESTORDATA, _investor)); + (_nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited) = VersionUtils.unpackKYC(data); + } + + function _isExistingInvestor(address _investor, IDataStore dataStore) internal view returns(bool) { + uint256 data = dataStore.getUint256(_getKey(KYCDATA, _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(_getKey(INVESTORS)); + } + + /** + * @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(_getKey(INVESTORS), _fromIndex, _toIndex); } /** * @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 + ) { + investors = getAllInvestors(); + (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _kycData(investors); + return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); + + } + + /** + * @dev Returns list of specified investors data + */ + function getKYCData(address[] calldata _investors) external view returns( + uint256[] memory, + uint256[] memory, + uint256[] memory, + bool[] memory, + bool[] memory + ) { + return _kycData(_investors); + } + + function _kycData(address[] memory _investors) internal view returns( + 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; + 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, isAccrediteds); + } + + /** + * @dev Returns list of all investors data + */ + function getAllInvestorsData() external view returns( + address[] memory investors, + uint256[] memory nonAccreditedLimitUSDOverride, + bool[] memory canBuyFromSTO, + bool[] memory isAccredited ) { - (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _investorsData(getInvestors()); - return (getInvestors(), fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); + investors = getAllInvestors(); + (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _investorsData(investors); + return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); } diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index b481e31d5..3b3e5571f 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -6,13 +6,16 @@ pragma solidity ^0.5.0; contract GeneralTransferManagerStorage { bytes32 public constant WHITELIST = "WHITELIST"; + bytes32 public constant INVESTORS = "INVESTORS"; + bytes32 public constant KYCDATA = "KYCDATA"; + bytes32 public constant INVESTORDATA = "INVESTORDATA"; bytes32 public constant FLAGS = "FLAGS"; //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 @@ -37,9 +40,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 +51,5 @@ contract GeneralTransferManagerStorage { bool public allowAllWhitelistIssuances = true; //If true, time lock is ignored for burn transactions bool public allowAllBurnTransfers = false; - + } From abb3a84ff519ce9b078ebd52d9bdaff17b507f2a Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 12 Feb 2019 12:13:09 +0530 Subject: [PATCH 03/24] USDTSTO get accredited from datastore --- contracts/interfaces/IDataStore.sol | 8 + contracts/libraries/VersionUtils.sol | 18 -- contracts/modules/STO/USDTieredSTO.sol | 72 +++---- .../GeneralTransferManager.sol | 188 ++++++------------ .../storage/GeneralTransferManagerStorage.sol | 30 +-- contracts/storage/USDTieredSTOStorage.sol | 3 +- docs/investor_flags.md | 23 +++ 7 files changed, 142 insertions(+), 200 deletions(-) create mode 100644 docs/investor_flags.md 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/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 17774983a..f7db3f2aa 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -124,22 +124,4 @@ library VersionUtils { expiryTime = uint64(_packedVersion >> 8); added = uint8(_packedVersion); } - - /** - * @notice Used to packed the KYC data - */ - function packInvestorData(uint240 _a, uint8 _b, uint8 _c) internal pure returns(uint256) { - return (uint256(_a) << 16) | (uint256(_b) << 8) | uint256(_c); - } - - /** - * @notice Used to convert packed data into KYC data - * @param _packedVersion Packed data - */ - function unpackInvestorData(uint256 _packedVersion) internal pure returns(uint240 limit, uint8 added, uint8 accredited) { - limit = uint240(_packedVersion >> 16); - added = uint8(_packedVersion >> 8); - accredited = uint8(_packedVersion); - } - } diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index d4845225b..2ffbcf3a2 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 @@ -304,27 +286,22 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { } } - // /** - // * @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) { - // // - // // - // // Fetch list from Datastore then do the magic - // // - // // - // 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 Returns investor accredited & non-accredited override informatiomn + * @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 investors, bool[] memory accredited, uint256[] memory overrides) { + IDataStore dataStore = IDataStore(getDataStore()); + investors = dataStore.getAddressArray(_getKey(INVESTORS)); + 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]]; + } + } /** * @notice Function to set allowBeneficialInvestments (allow beneficiary to be different to funder) @@ -567,14 +544,23 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { function _isAccredited(address _investor) internal view returns(bool) { IDataStore dataStore = IDataStore(getDataStore()); - uint256 whitelistData = dataStore.getUint256(_getKey(WHITELIST, _investor)); - return (uint8(whitelistData) > 0); + 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; } function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } + function _getKey(bytes32 _key1) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1))); + } + ///////////// // Getters // ///////////// @@ -584,7 +570,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/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index bd747310e..6b9983c20 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -43,11 +43,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint256 _expiryTime ); - event ModifyInvestorData( + event ModifyInvestorFlag( address indexed _investor, - uint256 nonAccreditedLimitUSDOverride, - bool canBuyFromSTO, - bool isAccredited + uint8 indexed _flag, + bool _value ); /** @@ -226,13 +225,13 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage dataStore.insertAddress(_getKey(INVESTORS), _investor); } uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), uint8(1)); - dataStore.setUint256(_getKey(KYCDATA, _investor), _data); + dataStore.setUint256(_getKey(WHITELIST, _investor), _data); emit ModifyKYCData(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime); } /** * @notice Add or remove KYC info of an investor. - * @param _investor is the address to whitelist + * @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 @@ -258,85 +257,77 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage } /** - * @notice Used to modify investor data. - * @param _investor is the address to whitelist - * @param _nonAccreditedLimitUSDOverride Overrides default non accredited purchase limit for the investor. - * @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. + * @notice Used to modify investor Flag. + * @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 modifyInvestorData( + function modifyInvestorFlag( address _investor, - uint256 _nonAccreditedLimitUSDOverride, - bool _canBuyFromSTO, - bool _isAccredited + uint8 _flag, + bool _value ) public withPerm(WHITELIST) { - _modifyInvestorData(_investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited); + _modifyInvestorFlag(_investor, _flag, _value); } - function _modifyInvestorData(address _investor, uint256 _nonAccreditedLimitUSDOverride, bool _canBuyFromSTO, bool _isAccredited) internal { + function _modifyInvestorFlag(address _investor, uint8 _flag, bool _value) internal { require(_investor != address(0), "Invalid investor"); - uint8 canBuyFromSTO; - uint8 isAccredited; IDataStore dataStore = IDataStore(getDataStore()); if (!_isExistingInvestor(_investor, dataStore)) { dataStore.insertAddress(_getKey(INVESTORS), _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(KYCDATA, _investor), uint256(1)); + dataStore.setUint256(_getKey(WHITELIST, _investor), uint256(1)); } - canBuyFromSTO = _canBuyFromSTO ? 1 : 0; - isAccredited = _isAccredited ? 1 : 0; - uint256 _data = VersionUtils.packInvestorData(uint240(_nonAccreditedLimitUSDOverride), canBuyFromSTO, isAccredited); - dataStore.setUint256(_getKey(INVESTORDATA, _investor), _data); - emit ModifyInvestorData(_investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited); + uint256 flags = dataStore.getUint256(_getKey(INVESTORFLAGS, _investor)); + flags = flags | (ONE << _flag); + dataStore.setUint256(_getKey(INVESTORFLAGS, _investor), flags); + emit ModifyInvestorFlag(_investor, _flag, _value); } /** * @notice Used to modify investor data. * @param _investors List of the addresses to modify data about. - * @param _nonAccreditedLimitUSDOverride Overrides default non accredited purchase limit for the investor. - * @param _canBuyFromSTO An array of boolean values. - * @param _isAccredited An array of boolean values to differentiate whether the investor is Accredited or not. + * @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 modifyInvestorDataMulti( + function modifyInvestorFlagMulti( address[] memory _investors, - uint256[] memory _nonAccreditedLimitUSDOverride, - bool[] memory _canBuyFromSTO, - bool[] memory _isAccredited + uint8[] memory _flag, + bool[] memory _value ) public withPerm(WHITELIST) { require( - _investors.length == _nonAccreditedLimitUSDOverride.length && - _nonAccreditedLimitUSDOverride.length == _canBuyFromSTO.length && - _canBuyFromSTO.length == _isAccredited.length, + _investors.length == _flag.length && + _flag.length == _value.length, "Mismatched input lengths" ); for (uint256 i = 0; i < _investors.length; i++) { - _modifyInvestorData(_investors[i], _nonAccreditedLimitUSDOverride[i], _canBuyFromSTO[i], _isAccredited[i]); + _modifyInvestorFlag(_investors[i], _flag[i], _value[i]); } } /** * @notice Adds or removes addresses from the whitelist - can be called by anyone with a valid signature * @param _investor is the address to whitelist - * @param _nonAccreditedLimitUSDOverride Overrides default non accredited purchase limit for the investor. - * @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 _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 _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 modifyInvestorDataSigned( + function modifyKYCDataSigned( address _investor, - uint256 _nonAccreditedLimitUSDOverride, - bool _canBuyFromSTO, - bool _isAccredited, + uint256 _fromTime, + uint256 _toTime, + uint256 _expiryTime, uint256 _validFrom, uint256 _validTo, uint256 _nonce, @@ -351,10 +342,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(!nonceMap[_investor][_nonce], "Already used signature"); nonceMap[_investor][_nonce] = true; bytes32 hash = keccak256( - abi.encodePacked(this, _investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited, _validFrom, _validTo, _nonce) + abi.encodePacked(this, _investor, _fromTime, _toTime, _expiryTime, _validFrom, _validTo, _nonce) ); _checkSig(hash, _signature); - _modifyInvestorData(_investor, _nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited); + _modifyKYCData(_investor, _fromTime, _toTime, _expiryTime); } /** @@ -421,22 +412,12 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage uint8 added ) { - uint256 data = dataStore.getUint256(_getKey(KYCDATA, _investor)); + uint256 data = dataStore.getUint256(_getKey(WHITELIST, _investor)); (fromTime, toTime, expiryTime, added) = VersionUtils.unpackKYC(data); } - function _getInvestorValues(address _investor, IDataStore dataStore) internal view returns( - uint240 _nonAccreditedLimitUSDOverride, - uint8 _canBuyFromSTO, - uint8 _isAccredited - ) - { - uint256 data = dataStore.getUint256(_getKey(INVESTORDATA, _investor)); - (_nonAccreditedLimitUSDOverride, _canBuyFromSTO, _isAccredited) = VersionUtils.unpackKYC(data); - } - function _isExistingInvestor(address _investor, IDataStore dataStore) internal view returns(bool) { - uint256 data = dataStore.getUint256(_getKey(KYCDATA, _investor)); + uint256 data = dataStore.getUint256(_getKey(WHITELIST, _investor)); //extracts `added` from packed `_whitelistData` return uint8(data) == 0 ? false : true; } @@ -463,104 +444,65 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage investors = dataStore.getAddressArrayElements(_getKey(INVESTORS), _fromIndex, _toIndex); } - /** - * @dev Returns list of all investors data - */ - function getAllKYCData() external view returns( - address[] memory investors, - uint256[] memory fromTimes, - uint256[] memory toTimes, - uint256[] memory expiryTimes - ) { + function getAllInvestorFlags() public view returns(address[] memory investors, uint256[] memory flags) { investors = getAllInvestors(); - (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _kycData(investors); - return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); + 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; } - /** - * @dev Returns list of specified investors data - */ - function getKYCData(address[] calldata _investors) external view returns( - uint256[] memory, - uint256[] memory, - uint256[] memory, - bool[] memory, - bool[] memory - ) { - return _kycData(_investors); + function getInvestorFlags(address _investor) public view returns(uint256 flags) { + flags = _getInvestorFlags(_investor); } - function _kycData(address[] memory _investors) internal view returns( - 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; - 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, isAccrediteds); + 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( + function getAllKYCData() external view returns( address[] memory investors, - uint256[] memory nonAccreditedLimitUSDOverride, - bool[] memory canBuyFromSTO, - bool[] memory isAccredited + uint256[] memory fromTimes, + uint256[] memory toTimes, + uint256[] memory expiryTimes ) { investors = getAllInvestors(); - (fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds) = _investorsData(investors); - return (investors, fromTimes, toTimes, expiryTimes, canBuyFromSTOs, isAccrediteds); - + (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 3b3e5571f..9bcca4121 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -7,9 +7,9 @@ contract GeneralTransferManagerStorage { bytes32 public constant WHITELIST = "WHITELIST"; bytes32 public constant INVESTORS = "INVESTORS"; - bytes32 public constant KYCDATA = "KYCDATA"; - bytes32 public constant INVESTORDATA = "INVESTORDATA"; + bytes32 public constant INVESTORFLAGS = "INVESTORFLAGS"; bytes32 public constant FLAGS = "FLAGS"; + uint256 internal constant ONE = uint256(1); //Address from which issuances come address public issuanceAddress; @@ -17,20 +17,20 @@ contract GeneralTransferManagerStorage { //Address which can sign whitelist changes 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 + // 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; diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index 0b97d70b2..b70692e69 100644 --- a/contracts/storage/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -7,7 +7,8 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; */ contract USDTieredSTOStorage { - bytes32 internal constant WHITELIST = "WHITELIST"; + bytes32 internal constant INVESTORFLAGS = "INVESTORFLAGS"; + bytes32 internal constant INVESTORS = "INVESTORS"; ///////////// // Storage // diff --git a/docs/investor_flags.md b/docs/investor_flags.md new file mode 100644 index 000000000..fb71bde77 --- /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 not Accredited.
1 canBuyFromSto Defines if an Investor has special permission to buy from STOs
From 77081e465d2e3d850a417d0d2a48c86fcafb9cbf Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 12 Feb 2019 13:51:52 +0530 Subject: [PATCH 04/24] can buy flag --- contracts/modules/STO/CappedSTO.sol | 6 +++--- contracts/modules/STO/DummySTO.sol | 1 + contracts/modules/STO/PreSaleSTO.sol | 13 +++++++------ contracts/modules/STO/STO.sol | 10 ++++++++++ contracts/modules/STO/STOStorage.sol | 1 + contracts/modules/STO/USDTieredSTO.sol | 6 ++---- contracts/storage/USDTieredSTOStorage.sol | 1 - 7 files changed, 24 insertions(+), 14 deletions(-) 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..dccf7d2be 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -70,4 +70,14 @@ 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 2ffbcf3a2..14ce6dbd7 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -417,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); @@ -553,10 +555,6 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { return flag > 0 ? true : false; } - function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(_key1, _key2))); - } - function _getKey(bytes32 _key1) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1))); } diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index b70692e69..2b9ca65fa 100644 --- a/contracts/storage/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -7,7 +7,6 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; */ contract USDTieredSTOStorage { - bytes32 internal constant INVESTORFLAGS = "INVESTORFLAGS"; bytes32 internal constant INVESTORS = "INVESTORS"; ///////////// From cd3f808165e5878270ad8cdef322e1557a202a7c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Tue, 12 Feb 2019 15:42:37 +0530 Subject: [PATCH 05/24] Investor list moved to data store --- contracts/interfaces/ISecurityToken.sol | 5 ++ contracts/libraries/TokenLib.sol | 64 +++++++++----- contracts/modules/STO/STO.sol | 1 - .../TransferManager/CountTransferManager.sol | 2 +- contracts/tokens/SecurityToken.sol | 84 ++++++++++--------- 5 files changed, 94 insertions(+), 62 deletions(-) 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 8585a3dba..db3784d57 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -3,10 +3,14 @@ pragma solidity ^0.5.0; import "../modules/PermissionManager/IPermissionManager.sol"; 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 INVESTORS = "INVESTORS"; + // Struct for module data struct ModuleData { bytes32 name; @@ -25,14 +29,14 @@ 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; - } + // 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, uint256 _timestamp); @@ -242,40 +246,58 @@ 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 - ) - public + 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(_getKey(INVESTORS), _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 _getKey(bytes32 _key1) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1))); + } + + 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/modules/STO/STO.sol b/contracts/modules/STO/STO.sol index dccf7d2be..ae69238fd 100644 --- a/contracts/modules/STO/STO.sol +++ b/contracts/modules/STO/STO.sol @@ -79,5 +79,4 @@ contract STO is ISTO, STOStorage, Module, Pausable { function _getKey(bytes32 _key1, address _key2) internal pure returns(bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - } 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/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 1bb6c9534..0fe9dd8a8 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -13,6 +13,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 @@ -27,7 +28,8 @@ import "../libraries/TokenLib.sol"; contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater { using SafeMath for uint256; - TokenLib.InvestorDataStorage investorData; + //TODO: Store keccak hash instead of investors to save gas. + bytes32 internal constant INVESTORS = "INVESTORS"; // Used to hold the semantic version data struct SemanticVersion { @@ -68,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; @@ -200,9 +205,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 +232,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); @@ -388,7 +393,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,33 +401,35 @@ 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(_getKey(INVESTORS)); } /** - * @notice returns an array of investors at a given checkpoint - * NB - this length may differ from investorCount as it contains all investors that ever held tokens + * @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(_getKey(INVESTORS)); + 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) { + investors[count] = investors[i]; count++; } } - return investors; + return holders; } /** @@ -433,22 +440,17 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @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(_getKey(INVESTORS), _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(_getKey(INVESTORS)); } /** @@ -571,10 +573,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 +650,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); @@ -840,4 +842,8 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater return _version; } + function _getKey(bytes32 _key1) internal pure returns(bytes32) { + return bytes32(keccak256(abi.encodePacked(_key1))); + } + } From 91468406af6b5e19c77e14eda6d04feca9824a1c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 12:32:28 +0530 Subject: [PATCH 06/24] Updated truffle --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a30b1040a..73a2273bf 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,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/yarn.lock b/yarn.lock index 05f706a51..10dc3fcac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7394,10 +7394,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" - integrity sha512-la0TJu+E59Ut62i6cGY0sugeubglDqH5w49a7IrpxZ1nnsDqv6qWB3ibiyYiCp/jr+iI0bLtcr3DKkfQjVDd+g== +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" From 7dd32c7f76d02695dc0ebbab028b4f0ea5a3dc03 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 12:32:39 +0530 Subject: [PATCH 07/24] Updated changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e428e11..b6e214ad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ 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. ## STR * Introduce new contract `STRGetter.sol`. It only contains the getter functions of the STR. @@ -19,7 +20,8 @@ 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 flags for Investors. ## Generalize * Removed `_polyAddress` parameter from constructors of all modules and module factories. From 76715a46cddc91fd8d881d8ef1385905dba9cb78 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 12:33:00 +0530 Subject: [PATCH 08/24] Fixed modifyWhitelist tests --- test/b_capped_sto.js | 16 ++-- test/c_checkpoints.js | 12 +-- test/d_count_transfer_manager.js | 24 +----- test/e_erc20_dividends.js | 16 +--- test/f_ether_dividends.js | 20 ++--- test/h_general_transfer_manager.js | 78 +++++-------------- 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 | 24 +++--- test/p_usd_tiered_sto.js | 41 ++++++---- test/q_usd_tiered_sto_sim.js | 12 +-- 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/zb_signed_transfer_manager.js | 4 +- 23 files changed, 116 insertions(+), 253 deletions(-) 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..64e34b398 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 @@ -379,8 +371,6 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -392,8 +382,6 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -405,8 +393,6 @@ contract("CountTransferManager", async (accounts) => { currentTime, currentTime, currentTime.add(new BN(duration.days(10))), - true, - false, { from: account_issuer, gas: 500000 @@ -418,8 +404,6 @@ contract("CountTransferManager", async (accounts) => { currentTime, 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 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..f17dce400 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -203,13 +203,11 @@ 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( + ${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,13 +220,11 @@ 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 @@ -257,7 +253,7 @@ contract("GeneralTransferManager", async (accounts) => { let times = range1(50); let bools = rangeB(50); - let tx = await I_GeneralTransferManager.modifyWhitelistMulti(mockInvestors, times, times, times, bools, bools, { + let tx = await I_GeneralTransferManager.modifyKYCDataMulti(mockInvestors, times, times, times, { from: account_issuer, gas: 7900000 }); @@ -358,13 +354,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 +416,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 +427,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 +468,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 +509,6 @@ contract("GeneralTransferManager", async (accounts) => { fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -526,13 +516,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 +545,6 @@ contract("GeneralTransferManager", async (accounts) => { fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -566,13 +552,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 +581,6 @@ contract("GeneralTransferManager", async (accounts) => { fromTime, toTime, expiryTime, - true, - false, validFrom, validTo, nonce, @@ -606,13 +588,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 +617,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 +665,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 +672,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 +701,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 +795,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 +814,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 +833,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 +852,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 +870,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/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..56d68b915 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 }); @@ -965,13 +965,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 +1006,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 diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1da3d9f20..109d31259 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1010,8 +1010,9 @@ 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)); @@ -1056,8 +1057,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.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)); @@ -1110,8 +1111,9 @@ 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)); @@ -1165,8 +1167,9 @@ 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)); @@ -1235,8 +1238,9 @@ 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)); @@ -1282,8 +1286,9 @@ 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)); @@ -1337,9 +1342,10 @@ 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)); @@ -1405,13 +1411,14 @@ 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"); }); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 8862bab3d..a82bb52a6 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -372,11 +372,13 @@ 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 increaseTime(duration.days(3)); 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/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 } From ac0b52a071f1cf1b1f389e10ffdfc0cdc1d91e3c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 13:24:00 +0530 Subject: [PATCH 09/24] typo fix --- contracts/tokens/SecurityToken.sol | 2 +- test/d_count_transfer_manager.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index a4d22cae5..3abef75b2 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -425,7 +425,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater count = 0; for (i = 0; i < investors.length; i++) { if (balanceOfAt(investors[i], _checkpointId) > 0) { - investors[count] = investors[i]; + holders[count] = investors[i]; count++; } } diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 64e34b398..b4758b749 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -366,7 +366,7 @@ contract("CountTransferManager", async (accounts) => { }); it("add 3 holders to the token", async () => { - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor1, currentTime, currentTime, @@ -377,7 +377,7 @@ contract("CountTransferManager", async (accounts) => { } ); - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor2, currentTime, currentTime, @@ -388,7 +388,7 @@ contract("CountTransferManager", async (accounts) => { } ); - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor3, currentTime, currentTime, @@ -399,7 +399,7 @@ contract("CountTransferManager", async (accounts) => { } ); - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyKYCData( account_investor4, currentTime, currentTime, From f641db84b44b990c850fe64547fd6e5270d9a5d3 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 13:54:13 +0530 Subject: [PATCH 10/24] Fixed gtm tests --- test/h_general_transfer_manager.js | 13 +++++++------ test/helpers/signData.js | 10 +++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index f17dce400..c43e69926 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -230,19 +230,20 @@ contract("GeneralTransferManager", async (accounts) => { 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 () => { @@ -259,7 +260,7 @@ contract("GeneralTransferManager", async (accounts) => { }); 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) ); }); 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; } From 2dc0286f4e96241eed9603534607431a8a84ba35 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 17:06:19 +0530 Subject: [PATCH 11/24] Fixed tests --- CHANGELOG.md | 5 +- contracts/datastore/DataStore.sol | 18 +- contracts/datastore/DataStoreStorage.sol | 4 +- contracts/storage/USDTieredSTOStorage.sol | 2 +- contracts/tokens/SecurityToken.sol | 6 +- test/d_count_transfer_manager.js | 4 +- test/j_manual_approval_transfer_manager.js | 796 ++++++++++----------- test/o_security_token.js | 22 +- test/p_usd_tiered_sto.js | 69 +- test/q_usd_tiered_sto_sim.js | 4 +- 10 files changed, 439 insertions(+), 491 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e214ad9..1a40be374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ All notable changes to this project will be documented in this file. * 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. @@ -21,7 +24,7 @@ All notable changes to this project will be documented in this file. ## GeneralTransferManager * `modifyWhitelist()` function renamed to `modifyKYCData()`. -* Added flags for Investors. +* Added functions to modify and get flags ## 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 5f6b03944..7ecacb553 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -15,22 +15,26 @@ contract DataStore is DataStoreStorage, IDataStore { 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), + _isAuthorized(); + _; + } + + 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"); _; } 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/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index 2b9ca65fa..894cac612 100644 --- a/contracts/storage/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -30,7 +30,7 @@ contract USDTieredSTOStorage { uint256 mintedDiscountPoly; } - mapping(address => uint256) nonAccreditedLimitUSDOverride; + mapping(address => uint256) public nonAccreditedLimitUSDOverride; mapping(bytes32 => mapping(bytes32 => string)) oracleKeys; diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 3abef75b2..856ee51e8 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -139,8 +139,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; @@ -434,7 +434,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater /** * @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 diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index b4758b749..64ac16798 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -449,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/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 2d3244e38..3708c8e92 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -428,403 +428,403 @@ contract("ManualApprovalTransferManager", accounts => { 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, - web3.utils.toWei("2", "ether"), - currentTime.add(new BN(duration.days(1))), - 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("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("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("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("Should decrease the allowance", async() => { - currentTime = new BN(await latestTime()); - await I_ManualApprovalTransferManager.modifyManualApproval( - account_investor1, - account_investor4, - expiryTimeMA, - web3.utils.toWei("1"), - web3.utils.fromAscii("New Description"), - 0, - { - 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("1")); - assert.equal(data[3].toString(), expiryTimeMA); - assert.equal(web3.utils.toUtf8(data[4]), "New Description"); - }); - - it("Should fail to transfer the tokens because allowance get changed", async() => { - await catchRevert( - I_SecurityToken.transfer(account_investor4, web3.utils.toWei("2"), {from: account_investor1}) - ); - }); - - it("Should successfully transfer the tokens within the allowance limit", async() => { - 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 modify because allowance is zero", async() => { - await catchRevert( - 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 revoke the manual Approval -- bad owner", async() => { - await catchRevert( - I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: account_investor5}) - ); - }) - - 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 revoke the same manual approval again", async() => { - await catchRevert( - I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}) - ); - }); - - 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("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 - } - ); - - 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("Should fail to revoke the multiple manual approvals -- because of bad owner", async() => { - await catchRevert( - I_ManualApprovalTransferManager.revokeManualApprovalMulti( - [account_investor2,account_investor3], - [account_investor3,account_investor4], - { - from: account_investor5 - } - ) - ); - }) - - it("Should fail to revoke the multiple manual approvals -- because of input length mismatch", async() => { - await catchRevert( - I_ManualApprovalTransferManager.revokeManualApprovalMulti( - [account_investor2,account_investor3], - [account_investor3], - { - from: token_owner - } - ) - ); - }) - - it("Revoke multiple manual approvals", async () => { - await I_ManualApprovalTransferManager.revokeManualApprovalMulti( - [account_investor2,account_investor3], - [account_investor3,account_investor4], - { - from: token_owner - } - ); - assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 0); - }); - - it("Add a manual approval for a 5th investor from issuance", async () => { - await I_ManualApprovalTransferManager.addManualApproval( - "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 () => { - let bytesCountTM = web3.eth.abi.encodeFunctionCall( - { - name: "configure", - type: "function", - inputs: [ - { - type: "uint256", - name: "_maxHolderCount" - } - ] - }, - [1] - ); - - const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].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); - }); - - it("Should get the permission list", async () => { - let perm = await I_ManualApprovalTransferManager.getPermissions.call(); - assert.equal(perm.length, 1); - }); - - it("Should get the init function", async () => { - let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); - assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ""), 0); - }); - }); - - describe("ManualApproval Transfer Manager Factory test cases", async () => { - it("Should get the exact details of the factory", async () => { - assert.equal(await I_ManualApprovalTransferManagerFactory.getSetupCost.call(), 0); - assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0], 2); - let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); - assert.equal(name, "ManualApprovalTransferManager", "Wrong Module added"); - let desc = await I_ManualApprovalTransferManagerFactory.description.call(); - 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 for specific pairs of addresses and amounts. Init function takes no parameters.", - "Wrong Module added" - ); - assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); - }); - - it("Should get the tags of the factory", async () => { - let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); - assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); - }); + // 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, + // web3.utils.toWei("2", "ether"), + // currentTime.add(new BN(duration.days(1))), + // 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("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("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("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("Should decrease the allowance", async() => { + // currentTime = new BN(await latestTime()); + // await I_ManualApprovalTransferManager.modifyManualApproval( + // account_investor1, + // account_investor4, + // expiryTimeMA, + // web3.utils.toWei("1"), + // web3.utils.fromAscii("New Description"), + // 0, + // { + // 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("1")); + // assert.equal(data[3].toString(), expiryTimeMA); + // assert.equal(web3.utils.toUtf8(data[4]), "New Description"); + // }); + + // it("Should fail to transfer the tokens because allowance get changed", async() => { + // await catchRevert( + // I_SecurityToken.transfer(account_investor4, web3.utils.toWei("2"), {from: account_investor1}) + // ); + // }); + + // it("Should successfully transfer the tokens within the allowance limit", async() => { + // 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 modify because allowance is zero", async() => { + // await catchRevert( + // 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 revoke the manual Approval -- bad owner", async() => { + // await catchRevert( + // I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: account_investor5}) + // ); + // }) + + // 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 revoke the same manual approval again", async() => { + // await catchRevert( + // I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}) + // ); + // }); + + // 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("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 + // } + // ); + + // 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("Should fail to revoke the multiple manual approvals -- because of bad owner", async() => { + // await catchRevert( + // I_ManualApprovalTransferManager.revokeManualApprovalMulti( + // [account_investor2,account_investor3], + // [account_investor3,account_investor4], + // { + // from: account_investor5 + // } + // ) + // ); + // }) + + // it("Should fail to revoke the multiple manual approvals -- because of input length mismatch", async() => { + // await catchRevert( + // I_ManualApprovalTransferManager.revokeManualApprovalMulti( + // [account_investor2,account_investor3], + // [account_investor3], + // { + // from: token_owner + // } + // ) + // ); + // }) + + // it("Revoke multiple manual approvals", async () => { + // await I_ManualApprovalTransferManager.revokeManualApprovalMulti( + // [account_investor2,account_investor3], + // [account_investor3,account_investor4], + // { + // from: token_owner + // } + // ); + // assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 0); + // }); + + // it("Add a manual approval for a 5th investor from issuance", async () => { + // await I_ManualApprovalTransferManager.addManualApproval( + // "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 () => { + // let bytesCountTM = web3.eth.abi.encodeFunctionCall( + // { + // name: "configure", + // type: "function", + // inputs: [ + // { + // type: "uint256", + // name: "_maxHolderCount" + // } + // ] + // }, + // [1] + // ); + + // const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); + // assert.equal(tx.logs[2].args._types[0].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); + // }); + + // it("Should get the permission list", async () => { + // let perm = await I_ManualApprovalTransferManager.getPermissions.call(); + // assert.equal(perm.length, 1); + // }); + + // it("Should get the init function", async () => { + // let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); + // assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ""), 0); + // }); + // }); + + // describe("ManualApproval Transfer Manager Factory test cases", async () => { + // it("Should get the exact details of the factory", async () => { + // assert.equal(await I_ManualApprovalTransferManagerFactory.getSetupCost.call(), 0); + // assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0], 2); + // let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); + // assert.equal(name, "ManualApprovalTransferManager", "Wrong Module added"); + // let desc = await I_ManualApprovalTransferManagerFactory.description.call(); + // 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 for specific pairs of addresses and amounts. Init function takes no parameters.", + // "Wrong Module added" + // ); + // assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); + // }); + + // it("Should get the tags of the factory", async () => { + // let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); + // assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); + // }); }); }); diff --git a/test/o_security_token.js b/test/o_security_token.js index 56d68b915..38fb10c81 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -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]); @@ -1091,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); @@ -1104,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 109d31259..4e3983966 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1011,15 +1011,12 @@ contract("USDTieredSTO", async (accounts) => { let whitelisted = true; await I_GeneralTransferManager.modifyKYCData(ACCREDITED1, fromTime, toTime, expiryTime, { from: ISSUER }); - await I_GeneralTransferManager.modifyInvestorFlag(ACCREDITED1, 0, true, { 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 @@ -1064,7 +1061,7 @@ contract("USDTieredSTO", async (accounts) => { 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 @@ -1118,9 +1115,6 @@ contract("USDTieredSTO", async (accounts) => { // 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); @@ -1174,9 +1168,6 @@ contract("USDTieredSTO", async (accounts) => { // 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"); @@ -1245,9 +1236,6 @@ contract("USDTieredSTO", async (accounts) => { // 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); @@ -1295,9 +1283,6 @@ contract("USDTieredSTO", async (accounts) => { 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 @@ -1350,9 +1335,6 @@ contract("USDTieredSTO", async (accounts) => { // 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"); @@ -1422,25 +1404,8 @@ contract("USDTieredSTO", async (accounts) => { 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"); @@ -1449,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"); }); }); @@ -1869,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); @@ -2170,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"); @@ -2186,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); @@ -2672,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, @@ -3447,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); @@ -3853,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); @@ -4069,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 a82bb52a6..22db5173b 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -383,8 +383,8 @@ contract("USDTieredSTO Sim", async (accounts) => { 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 }); }); }); From 3826624e25b17dbc346e74068625524363123558 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 17:20:01 +0530 Subject: [PATCH 12/24] Simulation fixed --- CHANGELOG.md | 1 + docs/investor_flags.md | 4 ++-- test/q_usd_tiered_sto_sim.js | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a40be374..94a8c2ce4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to this project will be documented in this file. ## 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/docs/investor_flags.md b/docs/investor_flags.md index fb71bde77..e52dfe280 100644 --- a/docs/investor_flags.md +++ b/docs/investor_flags.md @@ -16,8 +16,8 @@ 1 - canBuyFromSto - Defines if an Investor has special permission to buy from STOs + canNotBuyFromSto + Defines if an Investor is restricted from participating in STOs diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index 22db5173b..30e72d055 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -379,6 +379,7 @@ contract("USDTieredSTO Sim", async (accounts) => { 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)); From d50fcc37236658028f622285b68928de36ee8c2b Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 17:44:44 +0530 Subject: [PATCH 13/24] code cleanup --- contracts/libraries/TokenLib.sol | 9 --------- .../modules/TransferManager/GeneralTransferManager.sol | 6 ++---- contracts/storage/GeneralTransferManagerStorage.sol | 6 +----- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index e218e1174..3eb1dbf8b 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -28,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 diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 6b9983c20..6b434138a 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -179,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; @@ -258,6 +254,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage /** * @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. @@ -282,6 +279,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage //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)); } + //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)); flags = flags | (ONE << _flag); dataStore.setUint256(_getKey(INVESTORFLAGS, _investor), flags); diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index 9bcca4121..2e6aec614 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -19,18 +19,14 @@ contract GeneralTransferManagerStorage { // //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 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; From 4a8402bc58c228c099421003d9977e514d9d5aa6 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 17:57:23 +0530 Subject: [PATCH 14/24] Removed gas limit --- test/h_general_transfer_manager.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index c43e69926..4d0fc431c 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -255,8 +255,7 @@ contract("GeneralTransferManager", async (accounts) => { let times = range1(50); let bools = rangeB(50); let tx = await I_GeneralTransferManager.modifyKYCDataMulti(mockInvestors, times, times, times, { - from: account_issuer, - gas: 7900000 + from: account_issuer }); console.log("Multi Whitelist x 50: " + tx.receipt.gasUsed); assert.deepEqual( From 827dc89445275e4e5905e30ddb98b7f93b54d071 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 17:57:33 +0530 Subject: [PATCH 15/24] Added eth gas reporter --- package.json | 1 + truffle-config.js | 9 +- yarn.lock | 216 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 219 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 73a2273bf..7f6db602b 100644 --- a/package.json +++ b/package.json @@ -85,6 +85,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", diff --git a/truffle-config.js b/truffle-config.js index c6d636e97..8f690985f 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -69,6 +69,13 @@ module.exports = { } }, mocha: { - enableTimeouts: false + enableTimeouts: false, + reporter: 'eth-gas-reporter', + reporterOptions : { + currency: 'USD', + gasPrice: 5, + onlyCalledMethods: true, + showTimeSpent: true + } } }; diff --git a/yarn.lock b/yarn.lock index 10dc3fcac..d284979da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,10 +35,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" @@ -49,6 +83,13 @@ abbrev@1.0.x: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= +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" @@ -285,6 +326,11 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" 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= + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1556,7 +1602,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" @@ -1650,6 +1696,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" @@ -1783,6 +1839,16 @@ 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: + 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" @@ -1930,7 +1996,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" @@ -2723,6 +2789,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" @@ -3351,7 +3435,7 @@ forever-agent@~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: +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== @@ -3501,6 +3585,11 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" 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= + get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" @@ -3818,6 +3907,18 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== +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" @@ -3833,6 +3934,13 @@ http-https@^1.0.0: resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= +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" @@ -5549,6 +5657,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-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" @@ -5802,6 +5915,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" @@ -5877,6 +5997,11 @@ qs@6.5.2, qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 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== + query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" @@ -6021,7 +6146,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" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -6158,6 +6283,13 @@ 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" @@ -6165,6 +6297,13 @@ req-from@^1.0.1: 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" @@ -6172,6 +6311,15 @@ request-promise-core@1.1.1: 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" @@ -6182,7 +6330,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" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -6246,6 +6394,11 @@ resolve-from@^2.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" 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= + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -6560,6 +6713,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" @@ -6579,7 +6740,7 @@ shebang-regex@^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.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= @@ -6737,6 +6898,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-antlr@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.3.2.tgz#1cf9d019280550a31299dc380e87a310dc4ca154" @@ -7126,6 +7292,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" @@ -7218,6 +7400,23 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +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" @@ -7469,6 +7668,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 2ff6d5848d5275a7a74c9b7defc10ed3a816b88d Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 18:31:00 +0530 Subject: [PATCH 16/24] gas usage script --- package.json | 1 + scripts/gasUsage.sh | 8 +++++ truffle-config-gas.js | 81 +++++++++++++++++++++++++++++++++++++++++++ truffle-config.js | 9 +---- 4 files changed, 91 insertions(+), 8 deletions(-) create mode 100755 scripts/gasUsage.sh create mode 100644 truffle-config-gas.js diff --git a/package.json b/package.json index 7f6db602b..ae65bf94f 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", diff --git a/scripts/gasUsage.sh b/scripts/gasUsage.sh new file mode 100755 index 000000000..72467f60a --- /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 +echo 'yolo' +mv truffle-config-bk.js truffle-config.js \ No newline at end of file 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/truffle-config.js b/truffle-config.js index 8f690985f..c6d636e97 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -69,13 +69,6 @@ module.exports = { } }, mocha: { - enableTimeouts: false, - reporter: 'eth-gas-reporter', - reporterOptions : { - currency: 'USD', - gasPrice: 5, - onlyCalledMethods: true, - showTimeSpent: true - } + enableTimeouts: false } }; From 57e5bb86d05994a19790851bd6589d25e6a186c6 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Wed, 13 Feb 2019 19:59:38 +0530 Subject: [PATCH 17/24] script fix --- scripts/gasUsage.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/gasUsage.sh b/scripts/gasUsage.sh index 72467f60a..a7794d371 100755 --- a/scripts/gasUsage.sh +++ b/scripts/gasUsage.sh @@ -3,6 +3,6 @@ mv truffle-config.js truffle-config-bk.js cp truffle-config-gas.js truffle-config.js -#scripts/test.sh -echo 'yolo' +scripts/test.sh + mv truffle-config-bk.js truffle-config.js \ No newline at end of file From fbf7a457d5d04de52465881758288589a1518608 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Feb 2019 12:56:51 +0530 Subject: [PATCH 18/24] Added datastore tests --- test/za_datastore.js | 8 ++++++++ 1 file changed, 8 insertions(+) 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"); }); From dfedc2901db93c08a572eabb6fceb82c5b152d5c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Feb 2019 13:13:46 +0530 Subject: [PATCH 19/24] Added gtm tests --- .../TransferManager/GeneralTransferManager.sol | 8 -------- test/h_general_transfer_manager.js | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 6b434138a..bd05f85c1 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -372,14 +372,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 */ diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 4d0fc431c..b9462c906 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -201,6 +201,23 @@ 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.modifyKYCData.estimateGas( From 230aaa5c817056b3153d2c31c7c033d91148dccb Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Feb 2019 14:02:21 +0530 Subject: [PATCH 20/24] restored matm tests --- test/j_manual_approval_transfer_manager.js | 796 ++++++++++----------- 1 file changed, 398 insertions(+), 398 deletions(-) diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 3708c8e92..2d3244e38 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -428,403 +428,403 @@ contract("ManualApprovalTransferManager", accounts => { 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, - // web3.utils.toWei("2", "ether"), - // currentTime.add(new BN(duration.days(1))), - // 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("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("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("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("Should decrease the allowance", async() => { - // currentTime = new BN(await latestTime()); - // await I_ManualApprovalTransferManager.modifyManualApproval( - // account_investor1, - // account_investor4, - // expiryTimeMA, - // web3.utils.toWei("1"), - // web3.utils.fromAscii("New Description"), - // 0, - // { - // 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("1")); - // assert.equal(data[3].toString(), expiryTimeMA); - // assert.equal(web3.utils.toUtf8(data[4]), "New Description"); - // }); - - // it("Should fail to transfer the tokens because allowance get changed", async() => { - // await catchRevert( - // I_SecurityToken.transfer(account_investor4, web3.utils.toWei("2"), {from: account_investor1}) - // ); - // }); - - // it("Should successfully transfer the tokens within the allowance limit", async() => { - // 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 modify because allowance is zero", async() => { - // await catchRevert( - // 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 revoke the manual Approval -- bad owner", async() => { - // await catchRevert( - // I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: account_investor5}) - // ); - // }) - - // 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 revoke the same manual approval again", async() => { - // await catchRevert( - // I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}) - // ); - // }); - - // 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("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 - // } - // ); - - // 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("Should fail to revoke the multiple manual approvals -- because of bad owner", async() => { - // await catchRevert( - // I_ManualApprovalTransferManager.revokeManualApprovalMulti( - // [account_investor2,account_investor3], - // [account_investor3,account_investor4], - // { - // from: account_investor5 - // } - // ) - // ); - // }) - - // it("Should fail to revoke the multiple manual approvals -- because of input length mismatch", async() => { - // await catchRevert( - // I_ManualApprovalTransferManager.revokeManualApprovalMulti( - // [account_investor2,account_investor3], - // [account_investor3], - // { - // from: token_owner - // } - // ) - // ); - // }) - - // it("Revoke multiple manual approvals", async () => { - // await I_ManualApprovalTransferManager.revokeManualApprovalMulti( - // [account_investor2,account_investor3], - // [account_investor3,account_investor4], - // { - // from: token_owner - // } - // ); - // assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 0); - // }); - - // it("Add a manual approval for a 5th investor from issuance", async () => { - // await I_ManualApprovalTransferManager.addManualApproval( - // "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 () => { - // let bytesCountTM = web3.eth.abi.encodeFunctionCall( - // { - // name: "configure", - // type: "function", - // inputs: [ - // { - // type: "uint256", - // name: "_maxHolderCount" - // } - // ] - // }, - // [1] - // ); - - // const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); - // assert.equal(tx.logs[2].args._types[0].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); - // }); - - // it("Should get the permission list", async () => { - // let perm = await I_ManualApprovalTransferManager.getPermissions.call(); - // assert.equal(perm.length, 1); - // }); - - // it("Should get the init function", async () => { - // let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); - // assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ""), 0); - // }); - // }); - - // describe("ManualApproval Transfer Manager Factory test cases", async () => { - // it("Should get the exact details of the factory", async () => { - // assert.equal(await I_ManualApprovalTransferManagerFactory.getSetupCost.call(), 0); - // assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0], 2); - // let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); - // assert.equal(name, "ManualApprovalTransferManager", "Wrong Module added"); - // let desc = await I_ManualApprovalTransferManagerFactory.description.call(); - // 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 for specific pairs of addresses and amounts. Init function takes no parameters.", - // "Wrong Module added" - // ); - // assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); - // }); - - // it("Should get the tags of the factory", async () => { - // let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); - // assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); - // }); + 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, + web3.utils.toWei("2", "ether"), + currentTime.add(new BN(duration.days(1))), + 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("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("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("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("Should decrease the allowance", async() => { + currentTime = new BN(await latestTime()); + await I_ManualApprovalTransferManager.modifyManualApproval( + account_investor1, + account_investor4, + expiryTimeMA, + web3.utils.toWei("1"), + web3.utils.fromAscii("New Description"), + 0, + { + 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("1")); + assert.equal(data[3].toString(), expiryTimeMA); + assert.equal(web3.utils.toUtf8(data[4]), "New Description"); + }); + + it("Should fail to transfer the tokens because allowance get changed", async() => { + await catchRevert( + I_SecurityToken.transfer(account_investor4, web3.utils.toWei("2"), {from: account_investor1}) + ); + }); + + it("Should successfully transfer the tokens within the allowance limit", async() => { + 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 modify because allowance is zero", async() => { + await catchRevert( + 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 revoke the manual Approval -- bad owner", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: account_investor5}) + ); + }) + + 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 revoke the same manual approval again", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApproval(account_investor1, account_investor4, {from: token_owner}) + ); + }); + + 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("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 + } + ); + + 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("Should fail to revoke the multiple manual approvals -- because of bad owner", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + { + from: account_investor5 + } + ) + ); + }) + + it("Should fail to revoke the multiple manual approvals -- because of input length mismatch", async() => { + await catchRevert( + I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3], + { + from: token_owner + } + ) + ); + }) + + it("Revoke multiple manual approvals", async () => { + await I_ManualApprovalTransferManager.revokeManualApprovalMulti( + [account_investor2,account_investor3], + [account_investor3,account_investor4], + { + from: token_owner + } + ); + assert.equal(await I_ManualApprovalTransferManager.getTotalApprovalsLength.call(), 0); + }); + + it("Add a manual approval for a 5th investor from issuance", async () => { + await I_ManualApprovalTransferManager.addManualApproval( + "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 () => { + let bytesCountTM = web3.eth.abi.encodeFunctionCall( + { + name: "configure", + type: "function", + inputs: [ + { + type: "uint256", + name: "_maxHolderCount" + } + ] + }, + [1] + ); + + const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].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); + }); + + it("Should get the permission list", async () => { + let perm = await I_ManualApprovalTransferManager.getPermissions.call(); + assert.equal(perm.length, 1); + }); + + it("Should get the init function", async () => { + let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); + assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ""), 0); + }); + }); + + describe("ManualApproval Transfer Manager Factory test cases", async () => { + it("Should get the exact details of the factory", async () => { + assert.equal(await I_ManualApprovalTransferManagerFactory.getSetupCost.call(), 0); + assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0], 2); + let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); + assert.equal(name, "ManualApprovalTransferManager", "Wrong Module added"); + let desc = await I_ManualApprovalTransferManagerFactory.description.call(); + 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 for specific pairs of addresses and amounts. Init function takes no parameters.", + "Wrong Module added" + ); + assert.equal(await I_ManualApprovalTransferManagerFactory.version.call(), "2.1.0"); + }); + + it("Should get the tags of the factory", async () => { + let tags = await I_ManualApprovalTransferManagerFactory.getTags.call(); + assert.equal(web3.utils.toUtf8(tags[0]), "ManualApproval"); + }); }); }); From 5a2fe4db8a53c90e723ee2f52866fcdc28b210cb Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 14 Feb 2019 14:16:19 +0530 Subject: [PATCH 21/24] Optimized investors key --- contracts/libraries/TokenLib.sol | 8 ++------ contracts/modules/STO/USDTieredSTO.sol | 6 +----- .../TransferManager/GeneralTransferManager.sol | 12 ++++-------- .../storage/GeneralTransferManagerStorage.sol | 2 +- contracts/storage/USDTieredSTOStorage.sol | 2 +- contracts/tokens/SecurityToken.sol | 16 +++++----------- 6 files changed, 14 insertions(+), 32 deletions(-) diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 3eb1dbf8b..bbbf78bb9 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -8,7 +8,7 @@ library TokenLib { using SafeMath for uint256; bytes32 internal constant WHITELIST = "WHITELIST"; - bytes32 internal constant INVESTORS = "INVESTORS"; + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) // Struct for module data struct ModuleData { @@ -240,7 +240,7 @@ library TokenLib { _holderCount = _holderCount.add(1); IDataStore dataStore = IDataStore(_dataStore); if (!_isExistingInvestor(_to, dataStore)) { - dataStore.insertAddress(_getKey(INVESTORS), _to); + 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)); } @@ -257,10 +257,6 @@ library TokenLib { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function _getKey(bytes32 _key1) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(_key1))); - } - function _isExistingInvestor(address _investor, IDataStore dataStore) internal view returns(bool) { uint256 data = dataStore.getUint256(_getKey(WHITELIST, _investor)); //extracts `added` from packed `whitelistData` diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 03e527f7b..6de21c48d 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -294,7 +294,7 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { */ function getAccreditedData() external view returns (address[] memory investors, bool[] memory accredited, uint256[] memory overrides) { IDataStore dataStore = IDataStore(getDataStore()); - investors = dataStore.getAddressArray(_getKey(INVESTORS)); + investors = dataStore.getAddressArray(INVESTORSKEY); accredited = new bool[](investors.length); overrides = new uint256[](investors.length); for (uint256 i = 0; i < investors.length; i++) { @@ -555,10 +555,6 @@ contract USDTieredSTO is USDTieredSTOStorage, STO { return flag > 0 ? true : false; } - function _getKey(bytes32 _key1) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(_key1))); - } - ///////////// // Getters // ///////////// diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index bd05f85c1..87121e4f0 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -218,7 +218,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(_investor != address(0), "Invalid investor"); IDataStore dataStore = IDataStore(getDataStore()); if (!_isExistingInvestor(_investor, dataStore)) { - dataStore.insertAddress(_getKey(INVESTORS), _investor); + dataStore.insertAddress(INVESTORSKEY, _investor); } uint256 _data = VersionUtils.packKYC(uint64(_fromTime), uint64(_toTime), uint64(_expiryTime), uint8(1)); dataStore.setUint256(_getKey(WHITELIST, _investor), _data); @@ -275,7 +275,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage require(_investor != address(0), "Invalid investor"); IDataStore dataStore = IDataStore(getDataStore()); if (!_isExistingInvestor(_investor, dataStore)) { - dataStore.insertAddress(_getKey(INVESTORS), _investor); + 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)); } @@ -391,10 +391,6 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - function _getKey(bytes32 _key1) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(_key1))); - } - function _getKYCValues(address _investor, IDataStore dataStore) internal view returns( uint64 fromTime, uint64 toTime, @@ -423,7 +419,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage */ function getAllInvestors() public view returns(address[] memory investors) { IDataStore dataStore = IDataStore(getDataStore()); - investors = dataStore.getAddressArray(_getKey(INVESTORS)); + investors = dataStore.getAddressArray(INVESTORSKEY); } /** @@ -431,7 +427,7 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage */ function getInvestors(uint256 _fromIndex, uint256 _toIndex) public view returns(address[] memory investors) { IDataStore dataStore = IDataStore(getDataStore()); - investors = dataStore.getAddressArrayElements(_getKey(INVESTORS), _fromIndex, _toIndex); + investors = dataStore.getAddressArrayElements(INVESTORSKEY, _fromIndex, _toIndex); } function getAllInvestorFlags() public view returns(address[] memory investors, uint256[] memory flags) { diff --git a/contracts/storage/GeneralTransferManagerStorage.sol b/contracts/storage/GeneralTransferManagerStorage.sol index 2e6aec614..f246b3675 100644 --- a/contracts/storage/GeneralTransferManagerStorage.sol +++ b/contracts/storage/GeneralTransferManagerStorage.sol @@ -6,7 +6,7 @@ pragma solidity ^0.5.0; contract GeneralTransferManagerStorage { bytes32 public constant WHITELIST = "WHITELIST"; - bytes32 public constant INVESTORS = "INVESTORS"; + 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); diff --git a/contracts/storage/USDTieredSTOStorage.sol b/contracts/storage/USDTieredSTOStorage.sol index 894cac612..4e37c6dd1 100644 --- a/contracts/storage/USDTieredSTOStorage.sol +++ b/contracts/storage/USDTieredSTOStorage.sol @@ -7,7 +7,7 @@ import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; */ contract USDTieredSTOStorage { - bytes32 internal constant INVESTORS = "INVESTORS"; + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) ///////////// // Storage // diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 856ee51e8..9f7b7fe59 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -29,8 +29,7 @@ import "../interfaces/IDataStore.sol"; contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater { using SafeMath for uint256; - //TODO: Store keccak hash instead of investors to save gas. - bytes32 internal constant INVESTORS = "INVESTORS"; + bytes32 internal constant INVESTORSKEY = 0xdf3a8dd24acdd05addfc6aeffef7574d2de3f844535ec91e8e0f3e45dba96731; //keccak256(abi.encodePacked("INVESTORS")) // Used to hold the semantic version data struct SemanticVersion { @@ -403,7 +402,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function getInvestors() public view returns(address[] memory investors) { IDataStore dataStoreInstance = IDataStore(dataStore); - investors = dataStoreInstance.getAddressArray(_getKey(INVESTORS)); + investors = dataStoreInstance.getAddressArray(INVESTORSKEY); } /** @@ -415,7 +414,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater uint256 count; uint256 i; IDataStore dataStoreInstance = IDataStore(dataStore); - address[] memory investors = dataStoreInstance.getAddressArray(_getKey(INVESTORS)); + address[] memory investors = dataStoreInstance.getAddressArray(INVESTORSKEY); for (i = 0; i < investors.length; i++) { if (balanceOfAt(investors[i], _checkpointId) > 0) { count++; @@ -441,7 +440,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[] memory) { IDataStore dataStoreInstance = IDataStore(dataStore); - return dataStoreInstance.getAddressArrayElements(_getKey(INVESTORS), _start, _end); + return dataStoreInstance.getAddressArrayElements(INVESTORSKEY, _start, _end); } /** @@ -450,7 +449,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater */ function getInvestorCount() external view returns(uint256) { IDataStore dataStoreInstance = IDataStore(dataStore); - return dataStoreInstance.getAddressArrayLength(_getKey(INVESTORS)); + return dataStoreInstance.getAddressArrayLength(INVESTORSKEY); } /** @@ -840,9 +839,4 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater _version[2] = securityTokenVersion.patch; return _version; } - - function _getKey(bytes32 _key1) internal pure returns(bytes32) { - return bytes32(keccak256(abi.encodePacked(_key1))); - } - } From cdc941da0b7851f965a396b87c0dc212d5ec8296 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 15 Feb 2019 15:55:11 +0530 Subject: [PATCH 22/24] bug fix --- contracts/modules/TransferManager/GeneralTransferManager.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 87121e4f0..981830437 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -281,7 +281,10 @@ contract GeneralTransferManager is GeneralTransferManagerStorage, TransferManage } //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)); - flags = flags | (ONE << _flag); + if (_value) + flags = flags | (ONE << _flag); + else + flags = flags & ~(ONE << _flag); dataStore.setUint256(_getKey(INVESTORFLAGS, _investor), flags); emit ModifyInvestorFlag(_investor, _flag, _value); } From 7454cfed57eaa17310e9ecf88c98f8bc19a6e0a5 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 18 Feb 2019 10:16:47 +0530 Subject: [PATCH 23/24] minor changes --- contracts/datastore/DataStore.sol | 83 +++++++++++++++++----------- contracts/libraries/VersionUtils.sol | 4 ++ 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/contracts/datastore/DataStore.sol b/contracts/datastore/DataStore.sol index 7ecacb553..958f8c51d 100644 --- a/contracts/datastore/DataStore.sol +++ b/contracts/datastore/DataStore.sol @@ -14,11 +14,6 @@ contract DataStore is DataStoreStorage, IDataStore { //Delegate with MANAGEDATA permission can modify data. event SecurityTokenChanged(address indexed _oldSecurityToken, address indexed _newSecurityToken); - modifier onlyAuthorized() { - _isAuthorized(); - _; - } - function _isAuthorized() internal view { require(msg.sender == address(securityToken) || msg.sender == IOwnable(address(securityToken)).owner() || @@ -58,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 { + function setUint256(bytes32 _key, uint256 _data) external { + _isAuthorized(); _setData(_key, _data, false); } - function setBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { + function setBytes32(bytes32 _key, bytes32 _data) external { + _isAuthorized(); _setData(_key, _data, false); } - function setAddress(bytes32 _key, address _data) external onlyAuthorized { + function setAddress(bytes32 _key, address _data) external { + _isAuthorized(); _setData(_key, _data, false); } - function setBool(bytes32 _key, bool _data) external onlyAuthorized { + function setBool(bytes32 _key, bool _data) external { + _isAuthorized(); _setData(_key, _data, false); } - function setString(bytes32 _key, string calldata _data) external onlyAuthorized { + function setString(bytes32 _key, string calldata _data) external { + _isAuthorized(); _setData(_key, _data); } - function setBytes(bytes32 _key, bytes calldata _data) external onlyAuthorized { + function setBytes(bytes32 _key, bytes calldata _data) external { + _isAuthorized(); _setData(_key, _data); } @@ -87,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); } @@ -108,19 +113,23 @@ 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 { + function insertUint256(bytes32 _key, uint256 _data) external { + _isAuthorized(); _setData(_key, _data, true); } - function insertBytes32(bytes32 _key, bytes32 _data) external onlyAuthorized { + function insertBytes32(bytes32 _key, bytes32 _data) external { + _isAuthorized(); _setData(_key, _data, true); } - function insertAddress(bytes32 _key, address _data) external onlyAuthorized { + function insertAddress(bytes32 _key, address _data) external { + _isAuthorized(); _setData(_key, _data, true); } - function insertBool(bytes32 _key, bool _data) external onlyAuthorized { + function insertBool(bytes32 _key, bool _data) external { + _isAuthorized(); _setData(_key, _data, true); } @@ -130,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); } @@ -151,25 +164,29 @@ 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], 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], 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], 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], false); } @@ -180,25 +197,29 @@ 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++) { _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++) { _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++) { _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++) { _setData(_keys[i], _data[i], true); } diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index f7db3f2aa..e878389bb 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -111,6 +111,10 @@ library VersionUtils { * @notice Used to packed the KYC data */ 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); } From 86d5bab8aa1d2c2b05527809062d2cf4181b5d4c Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Mon, 18 Feb 2019 11:02:46 +0530 Subject: [PATCH 24/24] Typo fix --- docs/investor_flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/investor_flags.md b/docs/investor_flags.md index e52dfe280..9ccf74473 100644 --- a/docs/investor_flags.md +++ b/docs/investor_flags.md @@ -12,7 +12,7 @@ 0 isAccredited - Defines if an Investor is Accredited or not. True for Accredited, false for not not Accredited. + Defines if an Investor is Accredited or not. True for Accredited, false for not Accredited. 1