diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index f0249e2fd..c1269c331 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -155,8 +155,18 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } require(getUint(Encoder.getKey('registry', _moduleFactory)) == 0, "Module factory should not be pre-registered"); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); - uint8 moduleType = moduleFactory.getType(); - require(moduleType != 0, "Factory moduleType should not equal to 0"); + //Enforce type uniqueness + uint256 i; + uint256 j; + uint8[] memory moduleTypes = moduleFactory.getTypes(); + for (i = 1; i < moduleTypes.length; i++) { + for (j = 0; j < i; j++) { + require(moduleTypes[i] != moduleTypes[j], "Type mismatch"); + } + } + require(moduleTypes.length != 0, "Factory must have type"); + // NB - here we index by the first type of the module. + uint8 moduleType = moduleFactory.getTypes()[0]; set(Encoder.getKey('registry', _moduleFactory), uint256(moduleType)); set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length)); pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 438e2eef5..8f2229b59 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -278,7 +278,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return true; } - function _tickerStatus(string _ticker) internal returns(bool) { + function _tickerStatus(string _ticker) internal view returns(bool) { return getBool(Encoder.getKey("registeredTickers_status", _ticker)); } diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 38f2a9e0d..839bb26ed 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -24,7 +24,7 @@ interface IModuleFactory { /** * @notice Type of the Module factory */ - function getType() external view returns(uint8); + function getTypes() external view returns(uint8[]); /** * @notice Get the name of the Module diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index c36f45270..b0cbd22b1 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -33,14 +33,14 @@ interface ISecurityToken { * @notice Burn function used to burn the securityToken * @param _value No. of tokens that get burned */ - function burn(uint256 _value) external returns (bool success); + function burn(uint256 _value) external; /** * @notice Burn function used to burn the securityToken on behalf of someone else * @param _from Address for whom to burn tokens * @param _value No. of token that get burned */ - function burnFrom(address _from, uint256 _value) external returns (bool success); + function burnFrom(address _from, uint256 _value) external; event Minted(address indexed _to, uint256 _value); event Burnt(address indexed _burner, uint256 _value); @@ -101,7 +101,7 @@ interface ISecurityToken { * NB - this length may differ from investorCount if the list has not been pruned of zero-balance investors * @return length */ - function getInvestorsLength() external view returns (uint256); + function getInvestors() external view returns (address[]); /** * @notice gets current checkpoint ID @@ -116,12 +116,6 @@ interface ISecurityToken { */ function investors(uint256 _index) external view returns (address); - /** - * @notice gets the number of investors - * @return count of investors - */ - function investorCount() external view returns (uint256); - /** * @notice allows the owner to withdraw unspent POLY stored by them on the ST. * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee. @@ -180,12 +174,6 @@ interface ISecurityToken { */ function mintMulti(address[] _investors, uint256[] _values) external returns (bool success); - /** - * @notice used to set the token Burner address. It can only be called by the owner - * @param _tokenBurner Address of the token burner contract - */ - function setTokenBurner(address _tokenBurner) external; - /** * @notice Removes a module attached to the SecurityToken * @param _module address of module to archive @@ -231,7 +219,15 @@ interface ISecurityToken { * @param _value amount of tokens to transfer * @param _data data attached to the transfer by controller to emit in event */ - function forceTransfer(address _from, address _to, uint256 _value, bytes _data) external returns(bool); + function forceTransfer(address _from, address _to, uint256 _value, bytes _data) external; + + /** + * @notice Use by a controller to execute a foced burn + * @param _from address from which to take tokens + * @param _value amount of tokens to transfer + * @param _data data attached to the transfer by controller to emit in event + */ + function forceBurn(address _from, uint256 _value, bytes _data) external; /** * @notice Use by the issuer to permanently disable controller functionality @@ -243,4 +239,9 @@ interface ISecurityToken { * @notice Use to get the version of the securityToken */ function getVersion() external view returns(uint8[]); + + /** + * @notice gets the investor count + */ + function getInvestorCount() external view returns(uint256); } diff --git a/contracts/interfaces/ITokenBurner.sol b/contracts/interfaces/ITokenBurner.sol deleted file mode 100644 index bf5ca0819..000000000 --- a/contracts/interfaces/ITokenBurner.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity ^0.4.24; - -/** - * @title Interface for the token burner contract - */ -interface ITokenBurner { - - function burn(address _burner, uint256 _value ) external returns(bool); - -} diff --git a/contracts/libraries/Encoder.sol b/contracts/libraries/Encoder.sol index edd446ef0..27d9a4ddf 100644 --- a/contracts/libraries/Encoder.sol +++ b/contracts/libraries/Encoder.sol @@ -1,8 +1,7 @@ pragma solidity ^0.4.24; - library Encoder { - + function getKey(string _key) internal pure returns (bytes32) { return bytes32(keccak256(abi.encodePacked(_key))); } @@ -10,21 +9,21 @@ library Encoder { function getKey(string _key1, address _key2) internal pure returns (bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - + function getKey(string _key1, string _key2) internal pure returns (bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - + function getKey(string _key1, uint256 _key2) internal pure returns (bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - + function getKey(string _key1, bytes32 _key2) internal pure returns (bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } - + function getKey(string _key1, bool _key2) internal pure returns (bytes32) { return bytes32(keccak256(abi.encodePacked(_key1, _key2))); } -} \ No newline at end of file +} diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol new file mode 100644 index 000000000..e8c76a4ce --- /dev/null +++ b/contracts/libraries/TokenLib.sol @@ -0,0 +1,193 @@ +pragma solidity ^0.4.24; + +import "../modules/PermissionManager/IPermissionManager.sol"; +import "./KindMath.sol"; + +library TokenLib { + + using KindMath for uint256; + + // Struct for module data + struct ModuleData { + bytes32 name; + address module; + address moduleFactory; + bool isArchived; + uint8[] moduleTypes; + uint256[] moduleIndexes; + uint256 nameIndex; + } + + // Structures to maintain checkpoints of balances for governance / dividends + struct Checkpoint { + uint256 checkpointId; + uint256 value; + } + + struct InvestorDataStorage { + // List of investors (may not be pruned to remove old investors with current zero balances) + mapping (address => bool) investorListed; + // List of token holders + address[] investors; + // Total number of non-zero token holders + uint256 investorCount; + } + + // Emit when Module get archived from the securityToken + event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp); + // Emit when Module get unarchived from the securityToken + event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp); + + /** + * @notice Archives a module attached to the SecurityToken + * @param _moduleData storage data + * @param _module address of module to archive + */ + function archiveModule(ModuleData storage _moduleData, address _module) public { + require(!_moduleData.isArchived, "Module archived"); + require(_moduleData.module != address(0), "Module missing"); + emit ModuleArchived(_moduleData.moduleTypes, _module, now); + _moduleData.isArchived = true; + } + + /** + * @notice Unarchives a module attached to the SecurityToken + * @param _moduleData storage data + * @param _module address of module to unarchive + */ + function unarchiveModule(ModuleData storage _moduleData, address _module) public { + require(_moduleData.isArchived, "Module unarchived"); + emit ModuleUnarchived(_moduleData.moduleTypes, _module, now); + _moduleData.isArchived = false; + } + + /** + * @notice Validate permissions with PermissionManager if it exists, If no Permission return false + * @dev Note that IModule withPerm will allow ST owner all permissions anyway + * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) + * @param _modules storage data + * @param _delegate address of delegate + * @param _module address of PermissionManager module + * @param _perm the permissions + * @return success + */ + function checkPermission(address[] storage _modules, address _delegate, address _module, bytes32 _perm) public view returns(bool) { + if (_modules.length == 0) { + return false; + } + + for (uint8 i = 0; i < _modules.length; i++) { + if (IPermissionManager(_modules[i]).checkPermission(_delegate, _module, _perm)) { + return true; + } + } + + return false; + } + + /** + * @notice Queries value at a defined checkpoint + * @param _checkpoints is array of Checkpoint objects + * @param _checkpointId Checkpoint ID to query + * @param _currentValue Current value of checkpoint + * @return uint256 + */ + function getValueAt(Checkpoint[] storage _checkpoints, uint256 _checkpointId, uint256 _currentValue) public view returns(uint256) { + //Checkpoint id 0 is when the token is first created - everyone has a zero balance + if (_checkpointId == 0) { + return 0; + } + if (_checkpoints.length == 0) { + return _currentValue; + } + if (_checkpoints[0].checkpointId >= _checkpointId) { + return _checkpoints[0].value; + } + if (_checkpoints[_checkpoints.length - 1].checkpointId < _checkpointId) { + return _currentValue; + } + if (_checkpoints[_checkpoints.length - 1].checkpointId == _checkpointId) { + return _checkpoints[_checkpoints.length - 1].value; + } + uint256 min = 0; + uint256 max = _checkpoints.length - 1; + while (max > min) { + uint256 mid = (max + min) / 2; + if (_checkpoints[mid].checkpointId == _checkpointId) { + max = mid; + break; + } + if (_checkpoints[mid].checkpointId < _checkpointId) { + min = mid + 1; + } else { + max = mid; + } + } + return _checkpoints[max].value; + } + + /** + * @notice store the changes to the checkpoint objects + * @param _checkpoints the affected checkpoint object array + * @param _newValue the new value that needs to be stored + */ + function adjustCheckpoints(TokenLib.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public { + //No checkpoints set yet + if (_currentCheckpointId == 0) { + return; + } + //No new checkpoints since last update + if ((_checkpoints.length > 0) && (_checkpoints[_checkpoints.length - 1].checkpointId == _currentCheckpointId)) { + return; + } + //New checkpoint, so record balance + _checkpoints.push( + TokenLib.Checkpoint({ + checkpointId: _currentCheckpointId, + value: _newValue + }) + ); + } + + /** + * @notice keeps track of the number of non-zero token holders + * @param _investorData Date releated to investor metrics + * @param _from sender of transfer + * @param _to receiver of transfer + * @param _value value of transfer + * @param _balanceTo balance of the _to address + * @param _balanceFrom balance of the _from address + */ + function adjustInvestorCount(InvestorDataStorage storage _investorData, address _from, address _to, uint256 _value, uint256 _balanceTo, uint256 _balanceFrom) public { + if ((_value == 0) || (_from == _to)) { + return; + } + // Check whether receiver is a new token holder + if ((_balanceTo == 0) && (_to != address(0))) { + _investorData.investorCount = (_investorData.investorCount).add(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; + } + + } + + /** + * @notice removes addresses with zero balances from the investors list + * @param _investorData Date releated to investor metrics + * @param _index Index in investor list + * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint + */ + function pruneInvestors(InvestorDataStorage storage _investorData, uint256 _index) public { + _investorData.investorListed[_investorData.investors[_index]] = false; + _investorData.investors[_index] = _investorData.investors[_investorData.investors.length - 1]; + _investorData.investors.length--; + } + +} diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 9b5f4fcc4..41689713d 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -5,12 +5,12 @@ pragma solidity ^0.4.24; */ library VersionUtils { - + /** * @notice This function is used to validate the version submitted * @param _current Array holds the present version of ST * @param _new Array holds the latest version of the ST - * @return bool + * @return bool */ function isValidVersion(uint8[] _current, uint8[] _new) internal pure returns(bool) { bool[] memory _temp = new bool[](_current.length); @@ -21,16 +21,16 @@ library VersionUtils { else _temp[i] = false; } - + for (i = 0; i < _current.length; i++) { if (i == 0) { if (_current[i] <= _new[i]) - if(_temp[0]) { + if(_temp[0]) { counter = counter + 3; break; } else counter++; - else + else return false; } else { if (_temp[i-1]) @@ -49,7 +49,7 @@ library VersionUtils { * @notice This function use to compare the lower bound with the latest version * @param _version1 Array holds the lower bound of the version * @param _version2 Array holds the latest version of the ST - * @return bool + * @return bool */ function compareLowerBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { require(_version1.length == _version2.length); @@ -71,16 +71,16 @@ library VersionUtils { if (counter == _version1.length - 1) return true; else - return false; + return false; } else - return true; + return true; } /** * @notice This function use to compare the upper bound with the latest version * @param _version1 Array holds the upper bound of the version * @param _version2 Array holds the latest version of the ST - * @return bool + * @return bool */ function compareUpperBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { require(_version1.length == _version2.length); @@ -102,12 +102,12 @@ library VersionUtils { if (counter == _version1.length - 1) return true; else - return false; + return false; } else - return true; + return true; } - + /** * @notice Use to pack the uint8[] array data into uint24 value * @param _major Major version @@ -129,6 +129,6 @@ library VersionUtils { _unpackVersion[2] = uint8(_packedVersion); return _unpackVersion; } - -} \ No newline at end of file + +} diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 2f7772d77..144db6b15 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -40,8 +40,9 @@ contract MockFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 0; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](0); + return res; } /** @@ -54,14 +55,14 @@ contract MockFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -82,14 +83,14 @@ contract MockFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Mock Manager - This is mock in nature"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Mock"; return availableTags; diff --git a/contracts/mocks/MockTokenBurner.sol b/contracts/mocks/MockTokenBurner.sol deleted file mode 100644 index cd5c4be23..000000000 --- a/contracts/mocks/MockTokenBurner.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.4.24; - -import "../interfaces/ITokenBurner.sol"; - -contract MockTokenBurner is ITokenBurner { - - address public securityToken; - - constructor (address _securityToken) public { - securityToken = _securityToken; - } - - function burn(address /* _burner */, uint256 /* _value */) public view returns(bool) { - require(msg.sender == securityToken); - // Add the schematics for the burner( token holder) that backing the burning of the securities - return true; - } - -} diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index 71521e242..71517dcb8 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -40,28 +40,30 @@ contract TestSTOFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 3; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 3; + return res; } /** * @notice Get the name of the Module */ - function getName() public view returns(bytes32) { + function getName() external view returns(bytes32) { return name; } /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -82,14 +84,14 @@ contract TestSTOFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Test STO - you can mint tokens at will"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Test"; availableTags[1] = "Non-refundable"; diff --git a/contracts/modules/Burn/TrackedRedemption.sol b/contracts/modules/Burn/TrackedRedemption.sol index f69d8a86a..44a0b1d0e 100644 --- a/contracts/modules/Burn/TrackedRedemption.sol +++ b/contracts/modules/Burn/TrackedRedemption.sol @@ -37,7 +37,7 @@ contract TrackedRedemption is IBurn, Module { * @param _value The number of tokens to redeem */ function redeemTokens(uint256 _value) public { - require(ISecurityToken(securityToken).burnFrom(msg.sender, _value), "Unable to redeem tokens"); + ISecurityToken(securityToken).burnFrom(msg.sender, _value); redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); emit Redeemed(msg.sender, _value, now); } diff --git a/contracts/modules/Burn/TrackedRedemptionFactory.sol b/contracts/modules/Burn/TrackedRedemptionFactory.sol index 94003286b..6611b2875 100644 --- a/contracts/modules/Burn/TrackedRedemptionFactory.sol +++ b/contracts/modules/Burn/TrackedRedemptionFactory.sol @@ -41,8 +41,10 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 5; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 5; + return res; } /** @@ -55,7 +57,7 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } @@ -69,7 +71,7 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -83,14 +85,14 @@ contract TrackedRedemptionFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Allows an investor to redeem security tokens which are tracked by this module"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Redemption"; availableTags[1] = "Tracked"; diff --git a/contracts/modules/Checkpoint/DividendCheckpoint.sol b/contracts/modules/Checkpoint/DividendCheckpoint.sol index fc70a9fde..1385637bc 100644 --- a/contracts/modules/Checkpoint/DividendCheckpoint.sol +++ b/contracts/modules/Checkpoint/DividendCheckpoint.sol @@ -131,9 +131,10 @@ contract DividendCheckpoint is ICheckpoint, Module { */ function pushDividendPayment(uint256 _dividendIndex, uint256 _start, uint256 _iterations) public withPerm(DISTRIBUTE) validDividendIndex(_dividendIndex) { Dividend storage dividend = dividends[_dividendIndex]; - uint256 numberInvestors = ISecurityToken(securityToken).getInvestorsLength(); - for (uint256 i = _start; i < Math.min256(numberInvestors, _start.add(_iterations)); i++) { - address payee = ISecurityToken(securityToken).investors(i); + address[] memory investors = ISecurityToken(securityToken).getInvestors(); + uint256 numberInvestors = Math.min256(investors.length, _start.add(_iterations)); + for (uint256 i = _start; i < numberInvestors; i++) { + address payee = investors[i]; if ((!dividend.claimed[payee]) && (!dividend.dividendExcluded[payee])) { _payDividend(payee, dividend, _dividendIndex); } diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index f71f601c6..8d3644510 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -1,100 +1,102 @@ -pragma solidity ^0.4.24; - -import "./ERC20DividendCheckpoint.sol"; -import "../ModuleFactory.sol"; - -/** - * @title Factory for deploying ERC20DividendCheckpoint module - */ -contract ERC20DividendCheckpointFactory is ModuleFactory { - - /** - * @notice Constructor - * @param _polyAddress Address of the polytoken - * @param _setupCost Setup cost of the module - * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module - */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { - version = "1.0.0"; - name = "ERC20DividendCheckpoint"; - title = "ERC20 Dividend Checkpoint"; - description = "Create ERC20 dividends for token holders at a specific checkpoint"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - } - - /** - * @notice used to launch the Module with the help of factory - * @return address Contract address of the Module - */ - function deploy(bytes /* _data */) external returns(address) { - if (setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); - emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); - return erc20DividendCheckpoint; - } - - /** - * @notice Type of the Module factory - */ - function getType() public view returns(uint8) { - return 4; - } - - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() public view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() public view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - - /** - * @notice Get the Instructions that helped to used the module - */ - function getInstructions() public view returns(string) { - return "Create a ERC20 dividend which will be paid out to token holders proportional to their balances at the point the dividend is created"; - } - - /** - * @notice Get the tags related to the module factory - */ - function getTags() public view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](3); - availableTags[0] = "ERC20"; - availableTags[1] = "Dividend"; - availableTags[2] = "Checkpoint"; - return availableTags; - } -} +pragma solidity ^0.4.24; + +import "./ERC20DividendCheckpoint.sol"; +import "../ModuleFactory.sol"; + +/** + * @title Factory for deploying ERC20DividendCheckpoint module + */ +contract ERC20DividendCheckpointFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "ERC20DividendCheckpoint"; + title = "ERC20 Dividend Checkpoint"; + description = "Create ERC20 dividends for token holders at a specific checkpoint"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /* _data */) external returns(address) { + if (setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + address erc20DividendCheckpoint = new ERC20DividendCheckpoint(msg.sender, address(polyToken)); + emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); + return erc20DividendCheckpoint; + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 4; + return res; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() external view returns(string) { + return description; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string) { + return title; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Get the Instructions that helped to used the module + */ + function getInstructions() external view returns(string) { + return "Create a ERC20 dividend which will be paid out to token holders proportional to their balances at the point the dividend is created"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](3); + availableTags[0] = "ERC20"; + availableTags[1] = "Dividend"; + availableTags[2] = "Checkpoint"; + return availableTags; + } +} diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index d1e8ac50b..487af022b 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -1,100 +1,102 @@ -pragma solidity ^0.4.24; - -import "./EtherDividendCheckpoint.sol"; -import "../ModuleFactory.sol"; - -/** - * @title Factory for deploying EtherDividendCheckpoint module - */ -contract EtherDividendCheckpointFactory is ModuleFactory { - - /** - * @notice Constructor - * @param _polyAddress Address of the polytoken - * @param _setupCost Setup cost of the module - * @param _usageCost Usage cost of the module - * @param _subscriptionCost Subscription cost of the module - */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { - version = "1.0.0"; - name = "EtherDividendCheckpoint"; - title = "Ether Dividend Checkpoint"; - description = "Create ETH dividends for token holders at a specific checkpoint"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - } - - /** - * @notice used to launch the Module with the help of factory - * @return address Contract address of the Module - */ - function deploy(bytes /* _data */) external returns(address) { - if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); - emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); - return ethDividendCheckpoint; - } - - /** - * @notice Type of the Module factory - */ - function getType() public view returns(uint8) { - return 4; - } - - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() public view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() public view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - - /** - * @notice Get the Instructions that helped to used the module - */ - function getInstructions() public view returns(string) { - return "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created"; - } - - /** - * @notice Get the tags related to the module factory - */ - function getTags() public view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](3); - availableTags[0] = "ETH"; - availableTags[1] = "Checkpoint"; - availableTags[2] = "Dividend"; - return availableTags; - } -} +pragma solidity ^0.4.24; + +import "./EtherDividendCheckpoint.sol"; +import "../ModuleFactory.sol"; + +/** + * @title Factory for deploying EtherDividendCheckpoint module + */ +contract EtherDividendCheckpointFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + * @param _setupCost Setup cost of the module + * @param _usageCost Usage cost of the module + * @param _subscriptionCost Subscription cost of the module + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "EtherDividendCheckpoint"; + title = "Ether Dividend Checkpoint"; + description = "Create ETH dividends for token holders at a specific checkpoint"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /* _data */) external returns(address) { + if(setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + address ethDividendCheckpoint = new EtherDividendCheckpoint(msg.sender, address(polyToken)); + emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); + return ethDividendCheckpoint; + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 4; + return res; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() external view returns(string) { + return description; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string) { + return title; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Get the Instructions that helped to used the module + */ + function getInstructions() external view returns(string) { + return "Create a dividend which will be paid out to token holders proportional to their balances at the point the dividend is created"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](3); + availableTags[0] = "ETH"; + availableTags[1] = "Checkpoint"; + availableTags[2] = "Dividend"; + return availableTags; + } +} diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index e6e6e65a1..078f408dc 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -14,7 +14,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { version = "1.0.0"; name = "GeneralPermissionManager"; title = "General Permission Manager"; @@ -38,8 +38,10 @@ contract GeneralPermissionManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 1; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 1; + return res; } /** @@ -52,14 +54,14 @@ contract GeneralPermissionManagerFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -80,14 +82,14 @@ contract GeneralPermissionManagerFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Add and remove permissions for the SecurityToken and associated modules. Permission types should be encoded as bytes32 values, and attached using the withPerm modifier to relevant functions.No initFunction required."; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](0); return availableTags; } diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 982f790f0..3c3597957 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -43,8 +43,10 @@ contract CappedSTOFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 3; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 3; + return res; } /** @@ -57,14 +59,14 @@ contract CappedSTOFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -85,14 +87,14 @@ contract CappedSTOFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Initialises a capped STO. Init parameters are _startTime (time STO starts), _endTime (time STO ends), _cap (cap in tokens for STO), _rate (POLY/ETH to token rate), _fundRaiseType (whether you are raising in POLY or ETH), _polyToken (address of POLY token), _fundsReceiver (address which will receive funds)"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Capped"; availableTags[1] = "Non-refundable"; diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index ec249b420..e4ddb8136 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -42,8 +42,10 @@ contract DummySTOFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 3; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 3; + return res; } /** @@ -56,14 +58,14 @@ contract DummySTOFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -84,14 +86,14 @@ contract DummySTOFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Dummy STO - you can mint tokens at will"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "Dummy"; availableTags[1] = "Non-refundable"; diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index 03ca13bbe..a939fce19 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -45,8 +45,10 @@ contract PreSaleSTOFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 3; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 3; + return res; } /** @@ -59,14 +61,14 @@ contract PreSaleSTOFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -87,14 +89,14 @@ contract PreSaleSTOFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Configure and track pre-sale token allocations"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](1); availableTags[0] = "Presale"; return availableTags; diff --git a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol index dc4d6c628..1f241d8cc 100644 --- a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol +++ b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol @@ -5,17 +5,15 @@ import "../../../interfaces/IUSDTieredSTOProxy.sol"; contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { - - constructor() public { } - + /** * @notice deploys the STO. * @param _securityToken Contract address of the securityToken * @param _polyAddress Contract address of the PolyToken. - * @param _factoryAddress Contract address of the factory + * @param _factoryAddress Contract address of the factory * @return address Address of the deployed STO */ function deploySTO(address _securityToken, address _polyAddress, address _factoryAddress) external returns (address) { @@ -31,4 +29,5 @@ contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { function getInitFunction(address _contractAddress) external returns (bytes4) { return USDTieredSTO(_contractAddress).getInitFunction(); } -} \ No newline at end of file + +} diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 1b01cec66..e5a459f73 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -17,7 +17,7 @@ contract USDTieredSTOFactory is ModuleFactory { */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _proxyFactoryAddress) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { require(_proxyFactoryAddress != address(0), "0x address is not allowed"); USDTieredSTOProxyAddress = _proxyFactoryAddress; version = "1.0.0"; @@ -49,8 +49,10 @@ contract USDTieredSTOFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 3; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 3; + return res; } /** @@ -63,14 +65,14 @@ contract USDTieredSTOFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -91,14 +93,14 @@ contract USDTieredSTOFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Initialises a USD tiered STO."; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](4); availableTags[0] = "USD"; availableTags[1] = "Tiered"; diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 274dae2d8..565a03033 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -28,7 +28,7 @@ contract CountTransferManager is ITransferManager { /// @notice Used to verify the transfer transaction according to the rule implemented in the trnasfer managers function verifyTransfer(address /* _from */, address _to, uint256 /* _amount */, bool /* _isTransfer */) public returns(Result) { if (!paused) { - if (maxHolderCount < ISecurityToken(securityToken).investorCount()) { + if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { // Allow transfers to existing maxHolders if (ISecurityToken(securityToken).balanceOf(_to) != 0) { return Result.NA; diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index aa7d2cda2..1fe47a853 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -15,7 +15,7 @@ contract CountTransferManagerFactory is ModuleFactory { */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { version = "1.0.0"; name = "CountTransferManager"; title = "Count Transfer Manager"; @@ -43,8 +43,10 @@ contract CountTransferManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 2; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; } /** @@ -57,14 +59,14 @@ contract CountTransferManagerFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -85,14 +87,14 @@ contract CountTransferManagerFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Allows an issuer to restrict the total number of non-zero token holders"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Count"; availableTags[1] = "Transfer Restriction"; diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index a3490130b..60e85f8f4 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -14,7 +14,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { version = "1.0.0"; name = "GeneralTransferManager"; title = "General Transfer Manager"; @@ -40,8 +40,10 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 2; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; } /** @@ -54,7 +56,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } @@ -68,7 +70,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -82,7 +84,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters."; } diff --git a/contracts/modules/TransferManager/ITransferManager.sol b/contracts/modules/TransferManager/ITransferManager.sol index 5d23a37fd..8279e68c5 100644 --- a/contracts/modules/TransferManager/ITransferManager.sol +++ b/contracts/modules/TransferManager/ITransferManager.sol @@ -5,6 +5,7 @@ import "../Module.sol"; /** * @title Interface to be implemented by all Transfer Manager modules + * @dev abstract contract */ contract ITransferManager is Module, Pausable { diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 2c0e60eb5..e3ad15901 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -17,7 +17,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { version = "1.0.0"; name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; @@ -41,8 +41,10 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { /** * @notice Type of the Module factory */ - function getType() public view returns(uint8) { - return 2; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; } /** @@ -55,17 +57,17 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } - + /** * @notice Get the version of the Module */ @@ -83,14 +85,14 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters."; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "ManualApproval"; availableTags[1] = "Transfer Restriction"; diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 59949880c..573c79ba1 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -15,7 +15,7 @@ contract PercentageTransferManagerFactory is ModuleFactory { */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { version = "1.0.0"; name = "PercentageTransferManager"; title = "Percentage Transfer Manager"; @@ -44,8 +44,10 @@ contract PercentageTransferManagerFactory is ModuleFactory { * @notice Type of the Module factory * @return uint8 */ - function getType() public view returns(uint8) { - return 2; + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; } /** @@ -58,14 +60,14 @@ contract PercentageTransferManagerFactory is ModuleFactory { /** * @notice Get the description of the Module */ - function getDescription() public view returns(string) { + function getDescription() external view returns(string) { return description; } /** * @notice Get the title of the Module */ - function getTitle() public view returns(string) { + function getTitle() external view returns(string) { return title; } @@ -86,14 +88,14 @@ contract PercentageTransferManagerFactory is ModuleFactory { /** * @notice Get the Instructions that helped to used the module */ - function getInstructions() public view returns(string) { + function getInstructions() external view returns(string) { return "Allows an issuer to restrict the total number of non-zero token holders"; } /** * @notice Get the tags related to the module factory */ - function getTags() public view returns(bytes32[]) { + function getTags() external view returns(bytes32[]) { bytes32[] memory availableTags = new bytes32[](2); availableTags[0] = "Percentage"; availableTags[1] = "Transfer Restriction"; diff --git a/contracts/tokens/STFactory.sol b/contracts/tokens/STFactory.sol index 6273cc69c..4277a8f29 100644 --- a/contracts/tokens/STFactory.sol +++ b/contracts/tokens/STFactory.sol @@ -10,9 +10,6 @@ contract STFactory is ISTFactory { address public transferManagerFactory; - // Should be set to false when we have more TransferManager options - bool addTransferManager = true; - constructor (address _transferManagerFactory) public { transferManagerFactory = _transferManagerFactory; } @@ -24,20 +21,15 @@ contract STFactory is ISTFactory { function deployToken(string _name, string _symbol, uint8 _decimals, string _tokenDetails, address _issuer, bool _divisible, address _polymathRegistry) external returns (address) { address newSecurityTokenAddress = new SecurityToken( - _name, - _symbol, - _decimals, - _divisible ? 1 : uint256(10)**_decimals, - _tokenDetails, - _polymathRegistry + _name, + _symbol, + _decimals, + _divisible ? 1 : uint256(10)**_decimals, + _tokenDetails, + _polymathRegistry ); - - if (addTransferManager) { - SecurityToken(newSecurityTokenAddress).addModule(transferManagerFactory, "", 0, 0); - } - + SecurityToken(newSecurityTokenAddress).addModule(transferManagerFactory, "", 0, 0); SecurityToken(newSecurityTokenAddress).transferOwnership(_issuer); - return newSecurityTokenAddress; } } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 8d73a9e00..83724284e 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -7,12 +7,12 @@ import "../interfaces/IModuleFactory.sol"; import "../interfaces/IModuleRegistry.sol"; import "../interfaces/IFeatureRegistry.sol"; import "../modules/TransferManager/ITransferManager.sol"; -import "../modules/PermissionManager/IPermissionManager.sol"; import "../RegistryUpdater.sol"; import "../libraries/Util.sol"; import "openzeppelin-solidity/contracts/ReentrancyGuard.sol"; import "openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol"; import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol"; +import "../libraries/TokenLib.sol"; /** * @title Security Token contract @@ -27,6 +27,8 @@ import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol"; contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, RegistryUpdater { using SafeMath for uint256; + TokenLib.InvestorDataStorage investorData; + // Use to hold the version struct SemanticVersion { uint8 major; @@ -34,28 +36,22 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr uint8 patch; } - SemanticVersion public securityTokenVersion; + SemanticVersion securityTokenVersion; // off-chain hash string public tokenDetails; - uint8 public constant PERMISSIONMANAGER_KEY = 1; - uint8 public constant TRANSFERMANAGER_KEY = 2; - uint8 public constant MINT_KEY = 3; - uint8 public constant CHECKPOINT_KEY = 4; - uint8 public constant BURN_KEY = 5; + uint8 constant PERMISSION_KEY = 1; + uint8 constant TRANSFER_KEY = 2; + uint8 constant MINT_KEY = 3; + uint8 constant CHECKPOINT_KEY = 4; + uint8 constant BURN_KEY = 5; uint256 public granularity; // Value of current checkpoint uint256 public currentCheckpointId; - // Total number of non-zero token holders - uint256 public investorCount; - - // List of token holders - address[] public investors; - // Use to temporarily halt all transactions bool public transfersFrozen; @@ -68,41 +64,27 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr // address whitelisted by issuer as controller address public controller; - struct ModuleData { - bytes32 name; - address module; - address moduleFactory; - bool isArchived; - uint8 moduleType; - uint256 moduleIndex; - uint256 nameIndex; - } - - // Structures to maintain checkpoints of balances for governance / dividends - struct Checkpoint { - uint256 checkpointId; - uint256 value; - } - - mapping (address => Checkpoint[]) public checkpointBalances; - Checkpoint[] public checkpointTotalSupply; - uint256[] public checkpointTimes; - // Records added modules - module list should be order agnostic! - mapping (uint8 => address[]) public modules; + mapping (uint8 => address[]) modules; // Records information about the module - mapping (address => ModuleData) modulesToData; + mapping (address => TokenLib.ModuleData) modulesToData; // Records added module names - module list should be order agnostic! mapping (bytes32 => address[]) names; - // List of investors - mapping (address => bool) public investorListed; + // Map each investor to a series of checkpoints + mapping (address => TokenLib.Checkpoint[]) checkpointBalances; + + // List of checkpoints that relate to total supply + TokenLib.Checkpoint[] checkpointTotalSupply; + + // Times at which each checkpoint was created + uint256[] checkpointTimes; // Emit at the time when module get added event ModuleAdded( - uint8 indexed _type, + uint8[] _types, bytes32 _name, address _moduleFactory, address _module, @@ -115,14 +97,14 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr event UpdateTokenDetails(string _oldDetails, string _newDetails); // Emit when the granularity get changed event GranularityChanged(uint256 _oldGranularity, uint256 _newGranularity); - // Emit when Module get removed from the securityToken - event ModuleRemoved(uint8 indexed _type, address _module, uint256 _timestamp); // Emit when Module get archived from the securityToken - event ModuleArchived(uint8 indexed _type, address _module, uint256 _timestamp); + event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp); // Emit when Module get unarchived from the securityToken - event ModuleUnarchived(uint8 indexed _type, address _module, uint256 _timestamp); + event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp); + // Emit when Module get removed from the securityToken + event ModuleRemoved(uint8[] _types, address _module, uint256 _timestamp); // Emit when the budget allocated to a module is changed - event ModuleBudgetChanged(uint8 indexed _moduleType, address _module, uint256 _oldBudget, uint256 _budget); + event ModuleBudgetChanged(uint8[] _moduleTypes, address _module, uint256 _oldBudget, uint256 _budget); // Emit when transfers are frozen or unfrozen event FreezeTransfers(bool _status, uint256 _timestamp); // Emit when new checkpoint created @@ -143,9 +125,13 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function _isModule(address _module, uint8 _type) internal view returns (bool) { require(modulesToData[_module].module == _module, "Address mismatch"); - require(modulesToData[_module].moduleType == _type, "Type mismatch"); require(!modulesToData[_module].isArchived, "Module archived"); - return true; + for (uint256 i = 0; i < modulesToData[_module].moduleTypes.length; i++) { + if (modulesToData[_module].moduleTypes[i] == _type) { + return true; + } + } + return false; } // Require msg.sender to be the specified module type @@ -170,7 +156,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } modifier isMintingAllowed() { - require(!mintingFrozen, "Minting is frozen"); + require(!mintingFrozen, "Minting frozen"); _; } @@ -183,7 +169,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @notice Revert if called by account which is not a controller */ modifier onlyController() { - require(msg.sender == controller, "Caller not controller"); + require(msg.sender == controller, "Not controller"); require(!controllerDisabled, "Controller disabled"); _; } @@ -217,11 +203,15 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } /** - * @notice Function used to attach the module in security token - * @param _moduleFactory Contract address of the module factory that needs to be attached - * @param _data Data used for the intialization of the module factory variables - * @param _maxCost Maximum cost of the Module factory - * @param _budget Budget of the Module factory + * @notice Function used to attach a module to the security token + * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it + * @dev to control restrictions on transfers. + * @dev You are allowed to add a new moduleType if: + * @dev - there is no existing module of that type yet added + * @dev - the last member of the module list is replacable + * @param _moduleFactory is the address of the module factory to be added + * @param _data is data packed into bytes used to further configure the module (See STO usage) + * @param _maxCost max amount of POLY willing to pay to module. (WIP) */ function addModule( address _moduleFactory, @@ -229,42 +219,31 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr uint256 _maxCost, uint256 _budget ) external onlyOwner nonReentrant { - _addModule(_moduleFactory, _data, _maxCost, _budget); - } - - /** - * @notice _addModule handles the attachment (or replacement) of modules for the ST - * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it - * @dev to control restrictions on transfers. - * @dev You are allowed to add a new moduleType if: - * @dev - there is no existing module of that type yet added - * @dev - the last member of the module list is replacable - * @param _moduleFactory is the address of the module factory to be added - * @param _data is data packed into bytes used to further configure the module (See STO usage) - * @param _maxCost max amount of POLY willing to pay to module. (WIP) - */ - function _addModule(address _moduleFactory, bytes _data, uint256 _maxCost, uint256 _budget) internal { //Check that module exists in registry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); - uint8 moduleType = moduleFactory.getType(); - /* require(modules[moduleType].length < MAX_MODULES, "Limit of MAX MODULES is reached"); */ + uint8[] memory moduleTypes = moduleFactory.getTypes(); uint256 moduleCost = moduleFactory.getSetupCost(); - require(moduleCost <= _maxCost, "Module cost too high"); + require(moduleCost <= _maxCost, "Cost too high"); //Approve fee for module - require(ERC20(polyToken).approve(_moduleFactory, moduleCost), "Insufficient funds for cost"); + require(ERC20(polyToken).approve(_moduleFactory, moduleCost), "Insufficient funds"); //Creates instance of module from factory address module = moduleFactory.deploy(_data); - require(modulesToData[module].module == address(0), "Module already exists"); + require(modulesToData[module].module == address(0), "Module exists"); //Approve ongoing budget - require(ERC20(polyToken).approve(module, _budget), "Insufficient funds for budget"); + require(ERC20(polyToken).approve(module, _budget), "Insufficient funds"); //Add to SecurityToken module map bytes32 moduleName = moduleFactory.getName(); - modulesToData[module] = ModuleData(moduleName, module, _moduleFactory, false, moduleType, modules[moduleType].length, names[moduleName].length); - modules[moduleType].push(module); + uint256[] memory moduleIndexes = new uint256[](moduleTypes.length); + uint256 i; + for (i = 0; i < moduleTypes.length; i++) { + moduleIndexes[i] = modules[moduleTypes[i]].length; + modules[moduleTypes[i]].push(module); + } + modulesToData[module] = TokenLib.ModuleData(moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length); names[moduleName].push(module); //Emit log event - emit ModuleAdded(moduleType, moduleName, _moduleFactory, module, moduleCost, _budget, now); + emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, now); } /** @@ -272,10 +251,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _module address of module to archive */ function archiveModule(address _module) external onlyOwner { - require(!modulesToData[_module].isArchived, "Module already archived"); - require(modulesToData[_module].module != address(0), "Module missing"); - emit ModuleArchived(modulesToData[_module].moduleType, _module, now); - modulesToData[_module].isArchived = true; + TokenLib.archiveModule(modulesToData[_module], _module); } /** @@ -283,9 +259,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _module address of module to unarchive */ function unarchiveModule(address _module) external onlyOwner { - require(modulesToData[_module].isArchived, "Module already unarchived"); - emit ModuleUnarchived(modulesToData[_module].moduleType, _module, now); - modulesToData[_module].isArchived = false; + TokenLib.unarchiveModule(modulesToData[_module], _module); } /** @@ -293,31 +267,44 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _module address of module to unarchive */ function removeModule(address _module) external onlyOwner { - require(modulesToData[_module].isArchived, "Module not archived"); + require(modulesToData[_module].isArchived, "Module archived"); require(modulesToData[_module].module != address(0), "Module missing"); - emit ModuleRemoved(modulesToData[_module].moduleType, _module, now); + emit ModuleRemoved(modulesToData[_module].moduleTypes, _module, now); // Remove from module type list - uint256 index = modulesToData[_module].moduleIndex; - uint8 moduleType = modulesToData[_module].moduleType; - uint256 length = modules[moduleType].length; - modules[moduleType][index] = modules[moduleType][length - 1]; - modules[moduleType].length = length - 1; - if ((length - 1) != index) { - modulesToData[modules[moduleType][index]].moduleIndex = index; + uint8[] memory moduleTypes = modulesToData[_module].moduleTypes; + for (uint256 i = 0; i < moduleTypes.length; i++) { + _removeModuleWithIndex(moduleTypes[i], modulesToData[_module].moduleIndexes[i]); + /* modulesToData[_module].moduleType[moduleTypes[i]] = false; */ } // Remove from module names list - index = modulesToData[_module].nameIndex; + uint256 index = modulesToData[_module].nameIndex; bytes32 name = modulesToData[_module].name; - length = names[name].length; + uint256 length = names[name].length; names[name][index] = names[name][length - 1]; names[name].length = length - 1; if ((length - 1) != index) { - modulesToData[modules[moduleType][index]].nameIndex = index; + modulesToData[names[name][index]].nameIndex = index; } // Remove from modulesToData delete modulesToData[_module]; } + function _removeModuleWithIndex(uint8 _type, uint256 _index) internal { + uint256 length = modules[_type].length; + modules[_type][_index] = modules[_type][length - 1]; + modules[_type].length = length - 1; + + if ((length - 1) != _index) { + //Need to find index of _type in moduleTypes of module we are moving + uint8[] memory newTypes = modulesToData[modules[_type][_index]].moduleTypes; + for (uint256 i = 0; i < newTypes.length; i++) { + if (newTypes[i] == _type) { + modulesToData[modules[_type][_index]].moduleIndexes[i] = _index; + } + } + } + } + /** * @notice Returns module list for a module type * @param _module address of the module @@ -326,18 +313,13 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return address module factory address * @return bool module archived * @return uint8 module type - * @return uint256 module index - * @return uint256 name index - */ - function getModule(address _module) external view returns (bytes32, address, address, bool, uint8, uint256, uint256) { + function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[]) { return (modulesToData[_module].name, modulesToData[_module].module, modulesToData[_module].moduleFactory, modulesToData[_module].isArchived, - modulesToData[_module].moduleType, - modulesToData[_module].moduleIndex, - modulesToData[_module].nameIndex); + modulesToData[_module].moduleTypes); } /** @@ -376,11 +358,11 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr require(modulesToData[_module].module != address(0), "Module missing"); uint256 _currentAllowance = IERC20(polyToken).allowance(address(this), _module); if (_budget < _currentAllowance) { - require(IERC20(polyToken).decreaseApproval(_module, _currentAllowance.sub(_budget)), "Insufficient balance to decreaseApproval"); + require(IERC20(polyToken).decreaseApproval(_module, _currentAllowance.sub(_budget)), "Insufficient balance"); } else { - require(IERC20(polyToken).increaseApproval(_module, _budget.sub(_currentAllowance)), "Insufficient balance to increaseApproval"); + require(IERC20(polyToken).increaseApproval(_module, _budget.sub(_currentAllowance)), "Insufficient balance"); } - emit ModuleBudgetChanged(modulesToData[_module].moduleType, _module, _currentAllowance, _budget); + emit ModuleBudgetChanged(modulesToData[_module].moduleTypes, _module, _currentAllowance, _budget); } /** @@ -397,7 +379,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _granularity granularity level of the token */ function changeGranularity(uint256 _granularity) external onlyOwner { - require(_granularity != 0, "Granularity can not be 0"); + require(_granularity != 0, "Incorrect granularity"); emit GranularityChanged(granularity, _granularity); granularity = _granularity; } @@ -409,23 +391,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _value value of transfer */ function _adjustInvestorCount(address _from, address _to, uint256 _value) internal { - if ((_value == 0) || (_from == _to)) { - return; - } - // Check whether receiver is a new token holder - if ((balanceOf(_to) == 0) && (_to != address(0))) { - investorCount = investorCount.add(1); - } - // Check whether sender is moving all of their tokens - if (_value == balanceOf(_from)) { - investorCount = investorCount.sub(1); - } - //Also adjust investor list - if (!investorListed[_to] && (_to != address(0))) { - investors.push(_to); - investorListed[_to] = true; - } - + TokenLib.adjustInvestorCount(investorData, _from, _to, _value, balanceOf(_to), balanceOf(_from)); } /** @@ -435,11 +401,9 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint */ function pruneInvestors(uint256 _start, uint256 _iters) external onlyOwner { - for (uint256 i = _start; i < Math.min256(_start.add(_iters), investors.length); i++) { - if ((i < investors.length) && (balanceOf(investors[i]) == 0)) { - investorListed[investors[i]] = false; - investors[i] = investors[investors.length - 1]; - investors.length--; + for (uint256 i = _start; i < Math.min256(_start.add(_iters), investorData.investors.length); i++) { + if ((i < investorData.investors.length) && (balanceOf(investorData.investors[i]) == 0)) { + TokenLib.pruneInvestors(investorData, i); } } } @@ -449,8 +413,15 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * NB - this length may differ from investorCount if list has not been pruned of zero balance investors * @return length */ - function getInvestorsLength() external view returns(uint256) { - return investors.length; + function getInvestors() external view returns(address[]) { + return investorData.investors; + } + + /** + * @notice gets the investor count + */ + function getInvestorCount() external view returns(uint256) { + return investorData.investorCount; } /** @@ -475,7 +446,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @notice adjust totalsupply at checkpoint after minting or burning tokens */ function _adjustTotalSupplyCheckpoints() internal { - _adjustCheckpoints(checkpointTotalSupply, totalSupply()); + TokenLib.adjustCheckpoints(checkpointTotalSupply, totalSupply(), currentCheckpointId); } /** @@ -483,40 +454,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _investor address of the token holder affected */ function _adjustBalanceCheckpoints(address _investor) internal { - _adjustCheckpoints(checkpointBalances[_investor], balanceOf(_investor)); - } - - /** - * @notice store the changes to the checkpoint objects - * @param _checkpoints the affected checkpoint object array - * @param _newValue the new value that needs to be stored - */ - function _adjustCheckpoints(Checkpoint[] storage _checkpoints, uint256 _newValue) internal { - //No checkpoints set yet - if (currentCheckpointId == 0) { - return; - } - //No previous checkpoint data - add current balance against checkpoint - if (_checkpoints.length == 0) { - _checkpoints.push( - Checkpoint({ - checkpointId: currentCheckpointId, - value: _newValue - }) - ); - return; - } - //No new checkpoints since last update - if (_checkpoints[_checkpoints.length - 1].checkpointId == currentCheckpointId) { - return; - } - //New checkpoint, so record balance - _checkpoints.push( - Checkpoint({ - checkpointId: currentCheckpointId, - value: _newValue - }) - ); + TokenLib.adjustCheckpoints(checkpointBalances[_investor], balanceOf(_investor), currentCheckpointId); } /** @@ -526,7 +464,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return bool success */ function transfer(address _to, uint256 _value) public returns (bool success) { - require(_updateTransfer(msg.sender, _to, _value), "Transfer is not valid"); + require(_updateTransfer(msg.sender, _to, _value), "Transfer not valid"); require(super.transfer(_to, _value)); return true; } @@ -539,7 +477,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return bool success */ function transferFrom(address _from, address _to, uint256 _value) public returns(bool) { - require(_updateTransfer(_from, _to, _value), "Transfer is not valid"); + require(_updateTransfer(_from, _to, _value), "Transfer not valid"); require(super.transferFrom(_from, _to, _value)); return true; } @@ -562,7 +500,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ function _verifyTransfer(address _from, address _to, uint256 _value, bool _isTransfer) internal checkGranularity(_value) returns (bool) { if (!transfersFrozen) { - if (modules[TRANSFERMANAGER_KEY].length == 0) { + if (modules[TRANSFER_KEY].length == 0) { return true; } bool isInvalid = false; @@ -570,8 +508,8 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr bool isForceValid = false; bool unarchived = false; address module; - for (uint8 i = 0; i < modules[TRANSFERMANAGER_KEY].length; i++) { - module = modules[TRANSFERMANAGER_KEY][i]; + for (uint8 i = 0; i < modules[TRANSFER_KEY].length; i++) { + module = modules[TRANSFER_KEY][i]; if (!modulesToData[module].isArchived) { unarchived = true; ITransferManager.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _isTransfer); @@ -588,8 +526,8 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } // If no unarchived modules, return true by default return unarchived ? (isForceValid ? true : (isInvalid ? false : isValid)) : true; - } - return false; + } + return false; } /** @@ -621,10 +559,8 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return success */ function mint(address _investor, uint256 _value) public onlyModuleOrOwner(MINT_KEY) checkGranularity(_value) isMintingAllowed() returns (bool success) { - require(_investor != address(0), "Investor address should not be 0x"); - _adjustInvestorCount(address(0), _investor, _value); - require(_verifyTransfer(address(0), _investor, _value, true), "Transfer is not valid"); - _adjustBalanceCheckpoints(_investor); + require(_investor != address(0), "Investor is 0"); + require(_updateTransfer(address(0), _investor, _value), "Transfer not valid"); _adjustTotalSupplyCheckpoints(); totalSupply_ = totalSupply_.add(_value); balances[_investor] = balances[_investor].add(_value); @@ -658,37 +594,26 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return success */ function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) { - if (modules[PERMISSIONMANAGER_KEY].length == 0) { - return false; - } - - for (uint8 i = 0; i < modules[PERMISSIONMANAGER_KEY].length; i++) { - if (IPermissionManager(modules[PERMISSIONMANAGER_KEY][i]).checkPermission(_delegate, _module, _perm)) { - return true; - } - } - - return false; + return TokenLib.checkPermission(modules[PERMISSION_KEY], _delegate, _module, _perm); } - function _burn(address _from, uint256 _value) internal returns (bool) { + function _burn(address _from, uint256 _value) internal returns(bool) { require(_value <= balances[_from], "Value too high"); - require(_updateTransfer(_from, address(0), _value), "Burn is not valid"); + bool verified = _updateTransfer(_from, address(0), _value); _adjustTotalSupplyCheckpoints(); balances[_from] = balances[_from].sub(_value); totalSupply_ = totalSupply_.sub(_value); emit Burnt(_from, _value); emit Transfer(_from, address(0), _value); - return true; + return verified; } /** * @notice Burn function used to burn the securityToken * @param _value No. of tokens that get burned */ - function burn(uint256 _value) checkGranularity(_value) onlyModule(BURN_KEY) public returns (bool) { - require(_burn(msg.sender, _value), "Invalid burn"); - return true; + function burn(uint256 _value) checkGranularity(_value) onlyModule(BURN_KEY) public { + require(_burn(msg.sender, _value), "Burn not valid"); } /** @@ -696,11 +621,10 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _from Address for whom to burn tokens * @param _value No. of tokens that get burned */ - function burnFrom(address _from, uint256 _value) checkGranularity(_value) onlyModule(BURN_KEY) public returns (bool) { + function burnFrom(address _from, uint256 _value) checkGranularity(_value) onlyModule(BURN_KEY) public { require(_value <= allowed[_from][msg.sender], "Value too high"); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); - require(_burn(_from, _value), "Invalid burn"); - return true; + require(_burn(_from, _value), "Burn not valid"); } /** @@ -729,49 +653,8 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @return uint256 */ function totalSupplyAt(uint256 _checkpointId) external view returns(uint256) { - return _getValueAt(checkpointTotalSupply, _checkpointId, totalSupply()); - } - - /** - * @notice Queries value at a defined checkpoint - * @param checkpoints is array of Checkpoint objects - * @param _checkpointId Checkpoint ID to query - * @param _currentValue Current value of checkpoint - * @return uint256 - */ - function _getValueAt(Checkpoint[] storage checkpoints, uint256 _checkpointId, uint256 _currentValue) internal view returns(uint256) { require(_checkpointId <= currentCheckpointId); - //Checkpoint id 0 is when the token is first created - everyone has a zero balance - if (_checkpointId == 0) { - return 0; - } - if (checkpoints.length == 0) { - return _currentValue; - } - if (checkpoints[0].checkpointId >= _checkpointId) { - return checkpoints[0].value; - } - if (checkpoints[checkpoints.length - 1].checkpointId < _checkpointId) { - return _currentValue; - } - if (checkpoints[checkpoints.length - 1].checkpointId == _checkpointId) { - return checkpoints[checkpoints.length - 1].value; - } - uint256 min = 0; - uint256 max = checkpoints.length - 1; - while (max > min) { - uint256 mid = (max + min) / 2; - if (checkpoints[mid].checkpointId == _checkpointId) { - max = mid; - break; - } - if (checkpoints[mid].checkpointId < _checkpointId) { - min = mid + 1; - } else { - max = mid; - } - } - return checkpoints[max].value; + return TokenLib.getValueAt(checkpointTotalSupply, _checkpointId, totalSupply()); } /** @@ -780,7 +663,8 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _checkpointId Checkpoint ID to query as of */ function balanceOfAt(address _investor, uint256 _checkpointId) public view returns(uint256) { - return _getValueAt(checkpointBalances[_investor], _checkpointId, balanceOf(_investor)); + require(_checkpointId <= currentCheckpointId); + return TokenLib.getValueAt(checkpointBalances[_investor], _checkpointId, balanceOf(_investor)); } /** @@ -811,16 +695,14 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _value amount of tokens to transfer * @param _data data attached to the transfer by controller to emit in event */ - function forceTransfer(address _from, address _to, uint256 _value, bytes _data) public onlyController returns(bool) { + function forceTransfer(address _from, address _to, uint256 _value, bytes _data) public onlyController { require(_to != address(0)); require(_value <= balances[_from]); bool verified = _updateTransfer(_from, _to, _value); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); - emit ForceTransfer(msg.sender, _from, _to, _value, verified, _data); emit Transfer(_from, _to, _value); - return true; } /** @@ -829,16 +711,9 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _value amount of tokens to transfer * @param _data data attached to the transfer by controller to emit in event */ - function forceBurn(address _from, uint256 _value, bytes _data) public onlyController returns(bool) { - require(_value <= balances[_from], "Value too high"); - bool verified = _updateTransfer(_from, address(0), _value); - _adjustTotalSupplyCheckpoints(); - balances[_from] = balances[_from].sub(_value); - totalSupply_ = totalSupply_.sub(_value); + function forceBurn(address _from, uint256 _value, bytes _data) public onlyController { + bool verified = _burn(_from, _value); emit ForceBurn(msg.sender, _from, _value, verified, _data); - emit Burnt(_from, _value); - emit Transfer(_from, address(0), _value); - return true; } /** diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 97124b804..7b1feeece 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -17,6 +17,8 @@ const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') const STFactory = artifacts.require('./tokens/STFactory.sol') const DevPolyToken = artifacts.require('./helpers/PolyTokenFaucet.sol') const MockOracle = artifacts.require('./MockOracle.sol') +const TokenLib = artifacts.require('./TokenLib.sol'); + let BigNumber = require('bignumber.js'); const cappedSTOSetupCost = new BigNumber(20000).times(new BigNumber(10).pow(18)); // 20K POLY fee const usdTieredSTOSetupCost = new BigNumber(100000).times(new BigNumber(10).pow(18)); // 100K POLY fee @@ -30,8 +32,9 @@ const Web3 = require('web3') module.exports = function (deployer, network, accounts) { // Ethereum account address hold by the Polymath (Act as the main account which have ownable permissions) - let PolymathAccount - let moduleRegistry + let PolymathAccount; + let moduleRegistry; + let polymathRegistry; let web3 if (network === 'development') { web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) @@ -52,6 +55,7 @@ module.exports = function (deployer, network, accounts) { ETHOracle = mockedOracle.address; }); }); + } else if (network === 'kovan') { web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/g5xfoQ0jFSE9S5LwM1Ei')) PolymathAccount = accounts[0] @@ -101,220 +105,223 @@ module.exports = function (deployer, network, accounts) { },{ type: 'address', name: '_owner' - } -] -}; + }] + }; -const functionSignatureProxyMR = { - name: 'initialize', - type: 'function', - inputs: [{ - type:'address', - name: '_polymathRegistry' - },{ - type: 'address', - name: '_owner' - } -] -}; + const functionSignatureProxyMR = { + name: 'initialize', + type: 'function', + inputs: [{ + type:'address', + name: '_polymathRegistry' + },{ + type: 'address', + name: '_owner' + }] + }; // POLYMATH NETWORK Configuration :: DO THIS ONLY ONCE // A) Deploy the PolymathRegistry contract return deployer.deploy(PolymathRegistry, {from: PolymathAccount}).then(() => { - return PolymathRegistry.deployed().then((polymathRegistry) => { - - return polymathRegistry.changeAddress("PolyToken", PolyToken, {from: PolymathAccount}) - .then(() => { - // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) - return deployer.deploy(ModuleRegistry, {from: PolymathAccount}); - }).then(() => { - return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); - }).then(() => { - let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [polymathRegistry.address, PolymathAccount]); - ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, {from: PolymathAccount}); - }).then(() => { - moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); - // Add module registry to polymath registry - return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); - }).then(() => { - // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this - // manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and - // this manager attach with the securityToken contract at the time of deployment) - return deployer.deploy(GeneralPermissionManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // D) Deploy the CountTransferManagerFactory Contract (Factory used to generate the CountTransferManager contract use - // to track the counts of the investors of the security token) - return deployer.deploy(CountTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use - // to track the percentage of investment the investors could do for a particular security token) - return deployer.deploy(PercentageTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use - // to provide the functionality of the dividend in terms of ETH) - return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use - // to provide the functionality of the dividend in terms of ERC20 token) - return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use - // to manual approve the transfer that will overcome the other transfer restrictions) - return deployer.deploy(ManualApprovalTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); - }).then(() => { - // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. - return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // K) Deploy the FeatureRegistry contract to control feature switches - return deployer.deploy(FeatureRegistry, PolymathRegistry.address, {from: PolymathAccount}); - }).then(() => { - // Assign the address into the FeatureRegistry key - return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, {from: PolymathAccount}); - }).then(() => { - // J) Deploy the SecurityTokenRegistry contract (Used to hold the deployed secuirtyToken details. It also act as the interface to deploy the SecurityToken) - return deployer.deploy(SecurityTokenRegistry, {from: PolymathAccount}) - }).then(()=> { - return deployer.deploy(SecurityTokenRegistryProxy, {from: PolymathAccount}); - }).then(() => { - let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolyToken, PolymathAccount]); - SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); - }).then(() => { - // Assign the address into the SecurityTokenRegistry key - return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); - }).then(() => { - // Update all addresses into the registry contract by calling the function updateFromregistry - return moduleRegistry.updateFromRegistry({from: PolymathAccount}); - }).then(() => { - // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the PercentageTransferManager contract. - return moduleRegistry.registerModule(PercentageTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // D) Register the CountTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the CountTransferManager contract. - return moduleRegistry.registerModule(CountTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // D) Register the GeneralTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the GeneralTransferManager contract. - return moduleRegistry.registerModule(GeneralTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the GeneralPermissionManager contract. - return moduleRegistry.registerModule(GeneralPermissionManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the GeneralPermissionManager contract. - return moduleRegistry.registerModule(EtherDividendCheckpointFactory.address, {from: PolymathAccount}); - }).then(() => { - // D) Register the ManualApprovalTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the ManualApprovalTransferManager contract. - return moduleRegistry.registerModule(ManualApprovalTransferManagerFactory.address, {from: PolymathAccount}); - }).then(() => { - // E) Register the ERC20DividendCheckpointFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the ERC20DividendCheckpoint contract. - return moduleRegistry.registerModule(ERC20DividendCheckpointFactory.address, {from: PolymathAccount}); - }).then(() => { - // F) Once the GeneralTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(GeneralTransferManagerFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the CountTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(CountTransferManagerFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the PercentageTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(PercentageTransferManagerFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the GeneralPermissionManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(GeneralPermissionManagerFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // G) Once the EtherDividendCheckpointFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(EtherDividendCheckpointFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the ERC20DividendCheckpointFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(ERC20DividendCheckpointFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // G) Once the ManualApprovalTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(ManualApprovalTransferManagerFactory.address, true, {from: PolymathAccount}); - }).then(() => { - // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). - return deployer.deploy(CappedSTOFactory, PolyToken, cappedSTOSetupCost, 0, 0, {from: PolymathAccount}) - }).then(() => { - // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the CappedSTOFactory contract. - return moduleRegistry.registerModule(CappedSTOFactory.address, {from: PolymathAccount}) - }).then(()=>{ - // G) Once the CappedSTOFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(CappedSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - // Deploy the proxy factory - return deployer.deploy(USDTieredSTOProxyFactory, {from: PolymathAccount}); - }).then(() => { - // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). - return deployer.deploy(USDTieredSTOFactory, PolyToken, usdTieredSTOSetupCost, 0, 0, USDTieredSTOProxyFactory.address, {from: PolymathAccount}) - }).then(() => { - // I) Register the USDTieredSTOFactory in the ModuleRegistry to make the factory available at the protocol level. - // So any securityToken can use that factory to generate the USDTieredSTOFactory contract. - return moduleRegistry.registerModule(USDTieredSTOFactory.address, {from: PolymathAccount}) - }).then(()=>{ - // J) Once the USDTieredSTOFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken - // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. - // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. - return moduleRegistry.verifyModule(USDTieredSTOFactory.address, true, {from: PolymathAccount}) - }).then(() => { - return polymathRegistry.changeAddress("PolyUsdOracle", POLYOracle, {from: PolymathAccount}); - }).then(() => { - return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, {from: PolymathAccount}); - }).then(() => { - console.log('\n'); - console.log(` - --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${ModuleRegistryProxy.address} - FeatureRegistry: ${FeatureRegistry.address} + return PolymathRegistry.deployed(); + }).then((_polymathRegistry) => { + polymathRegistry = _polymathRegistry; + return polymathRegistry.changeAddress("PolyToken", PolyToken, {from: PolymathAccount}); + }).then(() => { + // Deploy libraries + return deployer.deploy(TokenLib, {from: PolymathAccount}); + }).then(() => { + // Link libraries + return deployer.link(TokenLib, STFactory); + }).then(() => { + // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) + return deployer.deploy(ModuleRegistry, {from: PolymathAccount}); + }).then(() => { + return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); + }).then(() => { + let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [polymathRegistry.address, PolymathAccount]); + ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, {from: PolymathAccount}); + }).then(() => { + moduleRegistry = ModuleRegistry.at(ModuleRegistryProxy.address); + // Add module registry to polymath registry + return polymathRegistry.changeAddress("ModuleRegistry", ModuleRegistryProxy.address, {from: PolymathAccount}); + }).then(() => { + // B) Deploy the GeneralTransferManagerFactory Contract (Factory used to generate the GeneralTransferManager contract and this + // manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // C) Deploy the GeneralPermissionManagerFactory Contract (Factory used to generate the GeneralPermissionManager contract and + // this manager attach with the securityToken contract at the time of deployment) + return deployer.deploy(GeneralPermissionManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the CountTransferManagerFactory Contract (Factory used to generate the CountTransferManager contract use + // to track the counts of the investors of the security token) + return deployer.deploy(CountTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the PercentageTransferManagerFactory Contract (Factory used to generate the PercentageTransferManager contract use + // to track the percentage of investment the investors could do for a particular security token) + return deployer.deploy(PercentageTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the EtherDividendCheckpointFactory Contract (Factory used to generate the EtherDividendCheckpoint contract use + // to provide the functionality of the dividend in terms of ETH) + return deployer.deploy(EtherDividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the ERC20DividendCheckpointFactory Contract (Factory used to generate the ERC20DividendCheckpoint contract use + // to provide the functionality of the dividend in terms of ERC20 token) + return deployer.deploy(ERC20DividendCheckpointFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // D) Deploy the ManualApprovalTransferManagerFactory Contract (Factory used to generate the ManualApprovalTransferManager contract use + // to manual approve the transfer that will overcome the other transfer restrictions) + return deployer.deploy(ManualApprovalTransferManagerFactory, PolyToken, 0, 0, 0, {from: PolymathAccount}); + }).then(() => { + // H) Deploy the STVersionProxy001 Contract which contains the logic of deployment of securityToken. + return deployer.deploy(STFactory, GeneralTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // K) Deploy the FeatureRegistry contract to control feature switches + return deployer.deploy(FeatureRegistry, PolymathRegistry.address, {from: PolymathAccount}); + }).then(() => { + // Assign the address into the FeatureRegistry key + return polymathRegistry.changeAddress("FeatureRegistry", FeatureRegistry.address, {from: PolymathAccount}); + }).then(() => { + // J) Deploy the SecurityTokenRegistry contract (Used to hold the deployed secuirtyToken details. It also act as the interface to deploy the SecurityToken) + return deployer.deploy(SecurityTokenRegistry, {from: PolymathAccount}) + }).then(()=> { + return deployer.deploy(SecurityTokenRegistryProxy, {from: PolymathAccount}); + }).then(() => { + let bytesProxy = web3.eth.abi.encodeFunctionCall(functionSignatureProxy, [PolymathRegistry.address, STFactory.address, initRegFee, initRegFee, PolyToken, PolymathAccount]); + SecurityTokenRegistryProxy.at(SecurityTokenRegistryProxy.address).upgradeToAndCall("1.0.0", SecurityTokenRegistry.address, bytesProxy, {from: PolymathAccount}); + }).then(() => { + // Assign the address into the SecurityTokenRegistry key + return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); + }).then(() => { + // Update all addresses into the registry contract by calling the function updateFromregistry + return moduleRegistry.updateFromRegistry({from: PolymathAccount}); + }).then(() => { + // D) Register the PercentageTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the PercentageTransferManager contract. + return moduleRegistry.registerModule(PercentageTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the CountTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the CountTransferManager contract. + return moduleRegistry.registerModule(CountTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the GeneralTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the GeneralTransferManager contract. + return moduleRegistry.registerModule(GeneralTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the GeneralPermissionManager contract. + return moduleRegistry.registerModule(GeneralPermissionManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // E) Register the GeneralPermissionManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the GeneralPermissionManager contract. + return moduleRegistry.registerModule(EtherDividendCheckpointFactory.address, {from: PolymathAccount}); + }).then(() => { + // D) Register the ManualApprovalTransferManagerFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the ManualApprovalTransferManager contract. + return moduleRegistry.registerModule(ManualApprovalTransferManagerFactory.address, {from: PolymathAccount}); + }).then(() => { + // E) Register the ERC20DividendCheckpointFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the ERC20DividendCheckpoint contract. + return moduleRegistry.registerModule(ERC20DividendCheckpointFactory.address, {from: PolymathAccount}); + }).then(() => { + // F) Once the GeneralTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(GeneralTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the CountTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(CountTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the PercentageTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(PercentageTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the GeneralPermissionManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(GeneralPermissionManagerFactory.address, true, {from: PolymathAccount}) + }).then(() => { + // G) Once the EtherDividendCheckpointFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(EtherDividendCheckpointFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the ERC20DividendCheckpointFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(ERC20DividendCheckpointFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // G) Once the ManualApprovalTransferManagerFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(ManualApprovalTransferManagerFactory.address, true, {from: PolymathAccount}); + }).then(() => { + // M) Deploy the CappedSTOFactory (Use to generate the CappedSTO contract which will used to collect the funds ). + return deployer.deploy(CappedSTOFactory, PolyToken, cappedSTOSetupCost, 0, 0, {from: PolymathAccount}) + }).then(() => { + // N) Register the CappedSTOFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the CappedSTOFactory contract. + return moduleRegistry.registerModule(CappedSTOFactory.address, {from: PolymathAccount}) + }).then(()=>{ + // G) Once the CappedSTOFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(CappedSTOFactory.address, true, {from: PolymathAccount}) + }).then(() => { + // Deploy the proxy factory + return deployer.deploy(USDTieredSTOProxyFactory, {from: PolymathAccount}); + }).then(() => { + // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). + return deployer.deploy(USDTieredSTOFactory, PolyToken, usdTieredSTOSetupCost, 0, 0, USDTieredSTOProxyFactory.address, {from: PolymathAccount}) + }).then(() => { + // I) Register the USDTieredSTOFactory in the ModuleRegistry to make the factory available at the protocol level. + // So any securityToken can use that factory to generate the USDTieredSTOFactory contract. + return moduleRegistry.registerModule(USDTieredSTOFactory.address, {from: PolymathAccount}) + }).then(()=>{ + // J) Once the USDTieredSTOFactory registered with the ModuleRegistry contract then for making them accessble to the securityToken + // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. + // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. + return moduleRegistry.verifyModule(USDTieredSTOFactory.address, true, {from: PolymathAccount}) + }).then(() => { + return polymathRegistry.changeAddress("PolyUsdOracle", POLYOracle, {from: PolymathAccount}); + }).then(() => { + return polymathRegistry.changeAddress("EthUsdOracle", ETHOracle, {from: PolymathAccount}); + }).then(() => { + console.log('\n'); + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + FeatureRegistry: ${FeatureRegistry.address} - ETHOracle: ${ETHOracle} - POLYOracle: ${POLYOracle} + ETHOracle: ${ETHOracle} + POLYOracle: ${POLYOracle} - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - CappedSTOFactory: ${CappedSTOFactory.address} - USDTieredSTOFactory: ${USDTieredSTOFactory.address} - USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} + CappedSTOFactory: ${CappedSTOFactory.address} + USDTieredSTOFactory: ${USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} - CountTransferManagerFactory: ${CountTransferManagerFactory.address} - PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} - ManualApprovalTransferManagerFactory: - ${ManualApprovalTransferManagerFactory.address} + CountTransferManagerFactory: ${CountTransferManagerFactory.address} + PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} + ManualApprovalTransferManagerFactory: + ${ManualApprovalTransferManagerFactory.address} - EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} - ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} - ----------------------------------------------------------------------------- - `); - console.log('\n'); - // -------- END OF POLYMATH NETWORK Configuration -------// - }); + EtherDividendCheckpointFactory: ${EtherDividendCheckpointFactory.address} + ERC20DividendCheckpointFactory: ${ERC20DividendCheckpointFactory.address} + ----------------------------------------------------------------------------- + `); + console.log('\n'); + // -------- END OF POLYMATH NETWORK Configuration -------// }); -}); } diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index ec216c637..c753d22db 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -269,12 +269,12 @@ contract('CappedSTO', accounts => { const log = await promisifyLogWatch(I_SecurityToken_ETH.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken_ETH.modules(transferManagerKey, 0); + let moduleData = (await I_SecurityToken_ETH.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -358,7 +358,7 @@ contract('CappedSTO', accounts => { let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver]); const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); }); @@ -729,7 +729,7 @@ contract('CappedSTO', accounts => { let bytesSTO = encodeModuleCall(STOParameters, [startTime_ETH2, endTime_ETH2, cap, rate, [E_fundRaiseType], account_fundsReceiver]); const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); }); @@ -839,7 +839,7 @@ contract('CappedSTO', accounts => { for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type, stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(tx.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); } @@ -886,12 +886,12 @@ contract('CappedSTO', accounts => { const log = await promisifyLogWatch(I_SecurityToken_POLY.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); }); it("POLY: Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken_POLY.modules(transferManagerKey, 0); + let moduleData = (await I_SecurityToken_POLY.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -906,7 +906,7 @@ contract('CappedSTO', accounts => { const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); }); @@ -1102,7 +1102,7 @@ contract('CappedSTO', accounts => { describe("Test cases for the CappedSTOFactory", async() => { it("should get the exact details of the factory", async() => { assert.equal((await I_CappedSTOFactory.setupCost.call()).toNumber(), cappedSTOSetupCost); - assert.equal(await I_CappedSTOFactory.getType.call(),3); + assert.equal((await I_CappedSTOFactory.getTypes.call())[0],3); assert.equal(web3.utils.hexToString(await I_CappedSTOFactory.getName.call()), "CappedSTO", "Wrong Module added"); @@ -1264,7 +1264,7 @@ contract('CappedSTO', accounts => { const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[3].args._name),"CappedSTO","CappedSTOFactory module was not added"); I_CappedSTO_Array_POLY.push(CappedSTO.at(tx.logs[3].args._module)); }); diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index a9094c6c5..d094a2dfc 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -215,7 +215,7 @@ contract('Checkpoints', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -223,9 +223,13 @@ contract('Checkpoints', accounts => { ); }); + it("Should set controller to token owner", async () => { + await I_SecurityToken.setController(token_owner, {from: token_owner}); + }); + it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); }); @@ -353,19 +357,39 @@ contract('Checkpoints', accounts => { await I_SecurityToken.transfer(receiver, amount, { from: sender }); } if (Math.random() > 0.5) { - let n = BigNumber(Math.random().toFixed(10)).mul(10**17).toFixed(0); - let p = Math.random() * 3; - let r = Math.random() * 3; - let minter; - if (r < 1) { - minter = account_investor1; - } else if (r < 2) { - minter = account_investor2; - } else { - minter = account_investor3; - } - console.log("Minting: " + n.toString() + " to: " + minter); - await I_SecurityToken.mint(minter, n, { from: token_owner }); + let n = BigNumber(Math.random().toFixed(10)).mul(10**17).toFixed(0); + let p = Math.random() * 3; + let r = Math.random() * 3; + let minter; + if (r < 1) { + minter = account_investor1; + } else if (r < 2) { + minter = account_investor2; + } else { + minter = account_investor3; + } + console.log("Minting: " + n.toString() + " to: " + minter); + await I_SecurityToken.mint(minter, n, { from: token_owner }); + } + if (Math.random() > 0.5) { + let n = BigNumber(Math.random().toFixed(10)).mul(10**17); + let p = Math.random() * 3; + let r = Math.random() * 3; + let burner; + if (r < 1) { + burner = account_investor1; + } else if (r < 2) { + burner = account_investor2; + } else { + burner = account_investor3; + } + let burnerBalance = BigNumber(await I_SecurityToken.balanceOf(burner)); + if (n.gt(burnerBalance.div(2))) { + n = burnerBalance.div(2); + } + n = n.toFixed(0); + console.log("Burning: " + n.toString() + " from: " + burner); + await I_SecurityToken.forceBurn(burner, n, "", { from: token_owner }); } console.log("Checking Interim..."); for (let k = 0; k < cps.length; k++) { diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 75c938939..164538f50 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -256,7 +256,7 @@ contract('CountTransferManager', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -265,7 +265,7 @@ contract('CountTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -287,7 +287,7 @@ contract('CountTransferManager', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "CountTransferManagerFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -300,7 +300,7 @@ contract('CountTransferManager', accounts => { it("Should successfully attach the CountTransferManager with the security token", async () => { const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -477,7 +477,7 @@ contract('CountTransferManager', accounts => { describe("Test cases for the factory", async() => { it("should get the exact details of the factory", async() => { assert.equal(await I_CountTransferManagerFactory.setupCost.call(),0); - assert.equal(await I_CountTransferManagerFactory.getType.call(),2); + assert.equal((await I_CountTransferManagerFactory.getTypes.call())[0],2); assert.equal(web3.utils.toAscii(await I_CountTransferManagerFactory.getName.call()) .replace(/\u0000/g, ''), "CountTransferManager", diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index cdd1fa98d..9f8f71984 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -249,7 +249,7 @@ contract('ERC20DividendCheckpoint', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -258,7 +258,7 @@ contract('ERC20DividendCheckpoint', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -280,7 +280,7 @@ contract('ERC20DividendCheckpoint', accounts => { await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_ERC20DividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -293,7 +293,7 @@ contract('ERC20DividendCheckpoint', accounts => { it("Should successfully attach the ERC20DividendCheckpoint with the security token", async () => { const tx = await I_SecurityToken.addModule(I_ERC20DividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "ERC20DividendCheckpoint doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -938,7 +938,7 @@ contract('ERC20DividendCheckpoint', accounts => { describe("Test cases for the ERC20DividendCheckpointFactory", async() => { it("should get the exact details of the factory", async() => { assert.equal((await I_ERC20DividendCheckpointFactory.setupCost.call()).toNumber(), 0); - assert.equal(await I_ERC20DividendCheckpointFactory.getType.call(), 4); + assert.equal((await I_ERC20DividendCheckpointFactory.getTypes.call())[0], 4); assert.equal(web3.utils.toAscii(await I_ERC20DividendCheckpointFactory.getName.call()) .replace(/\u0000/g, ''), "ERC20DividendCheckpoint", diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index dec4be72f..b65a8f7c1 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -250,7 +250,7 @@ contract('EtherDividendCheckpoint', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -259,7 +259,7 @@ contract('EtherDividendCheckpoint', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -281,7 +281,7 @@ contract('EtherDividendCheckpoint', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_EtherDividendCheckpointFactory.address, "", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -294,7 +294,7 @@ contract('EtherDividendCheckpoint', accounts => { it("Should successfully attach the EtherDividendCheckpoint with the security token", async () => { const tx = await I_SecurityToken.addModule(I_EtherDividendCheckpointFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), checkpointKey, "EtherDividendCheckpoint doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -958,7 +958,7 @@ contract('EtherDividendCheckpoint', accounts => { describe("Test cases for the EtherDividendCheckpointFactory", async() => { it("should get the exact details of the factory", async() => { assert.equal((await I_EtherDividendCheckpointFactory.setupCost.call()).toNumber(), 0); - assert.equal(await I_EtherDividendCheckpointFactory.getType.call(), 4); + assert.equal((await I_EtherDividendCheckpointFactory.getTypes.call())[0], 4); assert.equal(web3.utils.toAscii(await I_EtherDividendCheckpointFactory.getName.call()) .replace(/\u0000/g, ''), "EtherDividendCheckpoint", diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index 3b7299ca2..32b501565 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -264,7 +264,7 @@ contract('GeneralPermissionManager', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -273,7 +273,7 @@ contract('GeneralPermissionManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -294,7 +294,7 @@ contract('GeneralPermissionManager', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -307,7 +307,7 @@ contract('GeneralPermissionManager', accounts => { it("Should successfully attach the General permission manager factory with the security token", async () => { const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "General Permission Manager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -398,7 +398,7 @@ contract('GeneralPermissionManager', accounts => { describe("General Permission Manager Factory test cases", async() => { it("should get the exact details of the factory", async() => { assert.equal(await I_GeneralPermissionManagerFactory.setupCost.call(),0); - assert.equal(await I_GeneralPermissionManagerFactory.getType.call(),1); + assert.equal((await I_GeneralPermissionManagerFactory.getTypes.call())[0],1); assert.equal(web3.utils.toAscii(await I_GeneralPermissionManagerFactory.getName.call()) .replace(/\u0000/g, ''), "GeneralPermissionManager", diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 36eccdbb0..232f7c1d2 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -251,7 +251,7 @@ contract('GeneralTransferManager', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -260,7 +260,7 @@ contract('GeneralTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -289,7 +289,7 @@ contract('GeneralTransferManager', accounts => { it("Should successfully attach the STO factory with the security token", async () => { let bytesSTO = encodeModuleCall(STOParameters, [latestTime() + duration.seconds(1000), latestTime() + duration.days(40), cap, someString]); const tx = await I_SecurityToken.addModule(I_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), stoKey, "DummySTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -301,7 +301,7 @@ contract('GeneralTransferManager', accounts => { it("Should successfully attach the permission manager factory with the security token", async () => { const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, 0, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -791,7 +791,7 @@ contract('GeneralTransferManager', accounts => { it("Should get the exact details of the factory", async() => { assert.equal(await I_GeneralTransferManagerFactory.setupCost.call(),0); - assert.equal(await I_GeneralTransferManagerFactory.getType.call(),2); + assert.equal((await I_GeneralTransferManagerFactory.getTypes.call())[0],2); assert.equal(web3.utils.toAscii(await I_GeneralTransferManagerFactory.getName.call()) .replace(/\u0000/g, ''), "GeneralTransferManager", @@ -817,7 +817,7 @@ contract('GeneralTransferManager', accounts => { describe("Dummy STO Factory test cases", async() => { it("should get the exact details of the factory", async() => { assert.equal(await I_DummySTOFactory.setupCost.call(),0); - assert.equal(await I_DummySTOFactory.getType.call(),3); + assert.equal((await I_DummySTOFactory.getTypes.call())[0],3); assert.equal(web3.utils.toAscii(await I_DummySTOFactory.getName.call()) .replace(/\u0000/g, ''), "DummySTO", diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 4cfe448d3..a9c502252 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -250,7 +250,7 @@ contract('Issuance', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -259,7 +259,7 @@ contract('Issuance', accounts => { }); it("POLYMATH: Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(transferManagerKey, 0); + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); @@ -287,7 +287,7 @@ contract('Issuance', accounts => { const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: account_polymath }); - assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -320,7 +320,7 @@ contract('Issuance', accounts => { it("Should add the delegate with permission", async() => { //First attach a permission manager to the token await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: account_polymath}); - let moduleData = await I_SecurityToken.modules(permissionManagerKey, 0); + let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); // Add permission to the deletgate (A regesteration process) await I_GeneralPermissionManager.addPermission(account_delegate, delegateDetails, { from: account_polymath}); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 9036435f8..cc6471e8a 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -265,12 +265,12 @@ contract('ManualApprovalTransferManager', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -349,7 +349,7 @@ contract('ManualApprovalTransferManager', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_ManualApprovalTransferManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "Manual Approval Transfer Manager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -363,7 +363,7 @@ contract('ManualApprovalTransferManager', accounts => { it("Should successfully attach the ManualApprovalTransferManager with the security token", async () => { const tx = await I_SecurityToken.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "ManualApprovalTransferManager doesn't get deployed"); assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManager module was not added"); I_ManualApprovalTransferManager = ManualApprovalTransferManager.at(tx.logs[2].args._module); }); @@ -653,7 +653,7 @@ contract('ManualApprovalTransferManager', accounts => { }, [1]); const tx = await I_SecurityToken.addModule(I_CountTransferManagerFactory.address, bytesCountTM, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); let name = web3.utils.toUtf8(tx.logs[2].args._name); assert.equal(name, "CountTransferManager", "CountTransferManager module was not added"); I_CountTransferManager = CountTransferManager.at(tx.logs[2].args._module); @@ -691,7 +691,7 @@ contract('ManualApprovalTransferManager', accounts => { it("Should get the exact details of the factory", async() => { assert.equal(await I_ManualApprovalTransferManagerFactory.setupCost.call(),0); - assert.equal(await I_ManualApprovalTransferManagerFactory.getType.call(),2); + assert.equal((await I_ManualApprovalTransferManagerFactory.getTypes.call())[0],2); let name = web3.utils.toUtf8(await I_ManualApprovalTransferManagerFactory.getName.call()); assert.equal(name,"ManualApprovalTransferManager","Wrong Module added"); let desc = await I_ManualApprovalTransferManagerFactory.getDescription.call(); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index a7ed18719..ae5bfb434 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -428,7 +428,7 @@ contract('ModuleRegistry', accounts => { let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner}); - assert.equal(tx.logs[2].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -444,7 +444,7 @@ contract('ModuleRegistry', accounts => { await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, {from: account_polymath}); await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, {from: account_polymath}); let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type, permissionManagerKey, "module doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "module doesn't get deployed"); }); it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async() => { diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index 4e81888f4..a3af87a97 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -259,7 +259,7 @@ contract('PercentageTransferManager', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -268,7 +268,7 @@ contract('PercentageTransferManager', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -347,7 +347,7 @@ contract('PercentageTransferManager', accounts => { let snapId = await takeSnapshot(); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), {from: token_owner}); const tx = await I_SecurityToken.addModule(P_PercentageTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type.toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManagerFactory doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[3].args._name) .replace(/\u0000/g, ''), @@ -360,7 +360,7 @@ contract('PercentageTransferManager', accounts => { it("Should successfully attach the PercentageTransferManager with the security token", async () => { const tx = await I_SecurityToken.addModule(I_PercentageTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "PercentageTransferManager doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -459,7 +459,7 @@ contract('PercentageTransferManager', accounts => { it("Should get the exact details of the factory", async() => { assert.equal(await I_PercentageTransferManagerFactory.setupCost.call(),0); - assert.equal(await I_PercentageTransferManagerFactory.getType.call(),2); + assert.equal((await I_PercentageTransferManagerFactory.getTypes.call())[0],2); assert.equal(web3.utils.toAscii(await I_PercentageTransferManagerFactory.getName.call()) .replace(/\u0000/g, ''), "PercentageTransferManager", diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 862885bcf..81ed48fd7 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -239,7 +239,7 @@ contract('PreSaleSTO', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -248,7 +248,7 @@ contract('PreSaleSTO', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(transferManagerKey, 0); + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -271,7 +271,7 @@ contract('PreSaleSTO', accounts => { const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type, stoKey, "PreSaleSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -455,7 +455,7 @@ contract('PreSaleSTO', accounts => { describe("Test cases for the PresaleSTOFactory", async() => { it("should get the exact details of the factory", async() => { assert.equal(await I_PreSaleSTOFactory.setupCost.call(),0); - assert.equal(await I_PreSaleSTOFactory.getType.call(),3); + assert.equal((await I_PreSaleSTOFactory.getTypes.call())[0],3); assert.equal(web3.utils.toAscii(await I_PreSaleSTOFactory.getName.call()) .replace(/\u0000/g, ''), "PreSaleSTO", diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 69d9623ad..7c47e12a9 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -557,7 +557,7 @@ contract('SecurityTokenRegistry', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTrasnferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); + assert.equal(log.args._types[0].toNumber(), transferManagerKey, `Should be equal to the ${transferManagerKey}`); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -620,7 +620,7 @@ contract('SecurityTokenRegistry', accounts => { const log = await promisifyLogWatch(I_SecurityToken002.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), diff --git a/test/o_security_token.js b/test/o_security_token.js index 1217c6c22..b6abc9b20 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -18,7 +18,6 @@ const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManage const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); -const TokenBurner = artifacts.require('./MockTokenBurner.sol'); const Web3 = require('web3'); const BigNumber = require('bignumber.js'); @@ -69,7 +68,6 @@ contract('SecurityToken', accounts => { let I_MRProxied; let I_CappedSTO; let I_PolyToken; - let I_TokenBurner; let I_PolymathRegistry; // SecurityToken Details (Launched ST on the behalf of the issuer) @@ -264,12 +262,13 @@ contract('SecurityToken', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + console.log(log.args); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal(web3.utils.toUtf8(log.args._name),"GeneralTransferManager"); }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(transferManagerKey, 0); + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); assert.notEqual( @@ -480,7 +479,7 @@ contract('SecurityToken', accounts => { const tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); - assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); assert.equal(web3.utils.toUtf8(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); }); @@ -515,9 +514,7 @@ contract('SecurityToken', accounts => { assert.equal(moduleData[1], I_CappedSTO.address); assert.equal(moduleData[2], I_CappedSTOFactory.address); assert.equal(moduleData[3], false); - assert.equal(moduleData[4], 3); - assert.equal(moduleData[5], 0); - assert.equal(moduleData[6], 0); + assert.equal(moduleData[4][0], 3); }); it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => { @@ -561,29 +558,29 @@ contract('SecurityToken', accounts => { assert.equal(log.logs[0].args._newDetails, "new token details"); }); - it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async() => { + it("Should fail to remove the module - module not archived", async() => { let errorThrown = false; try { - let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : account_temp }); + let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); } catch (error) { - console.log(`Test Case passed by restricting the unknown account to call removeModule of the securityToken`); + console.log(` tx -> Failed because address doesn't exist`); errorThrown = true; ensureException(error); } assert.ok(errorThrown, message); - }); + }) - it("Should fail to remove the module - module not archived", async() => { + it("Should successfully remove the general transfer manager module from the securityToken -- fails msg.sender should be Owner", async() => { let errorThrown = false; try { - let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); + let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : account_temp }); } catch (error) { - console.log(` tx -> Failed because address doesn't exist`); + console.log(`Test Case passed by restricting the unknown account to call removeModule of the securityToken`); errorThrown = true; ensureException(error); } assert.ok(errorThrown, message); - }) + }); it("Should fail to remove the module - incorrect address", async() => { let errorThrown = false; @@ -601,7 +598,7 @@ contract('SecurityToken', accounts => { let key = await takeSnapshot(); await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from : token_owner }); - assert.equal(tx.logs[0].args._type, transferManagerKey); + assert.equal(tx.logs[0].args._types[0], transferManagerKey); assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); await revertToSnapshot(key); }); @@ -615,7 +612,7 @@ contract('SecurityToken', accounts => { it("Should successfully archive the general transfer manager module from the securityToken", async() => { let tx = await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from : token_owner }); - assert.equal(tx.logs[0].args._type, transferManagerKey); + assert.equal(tx.logs[0].args._types[0], transferManagerKey); assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); @@ -634,7 +631,7 @@ contract('SecurityToken', accounts => { it("Should successfully unarchive the general transfer manager module from the securityToken", async() => { let tx = await I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from : token_owner }); - assert.equal(tx.logs[0].args._type, transferManagerKey); + assert.equal(tx.logs[0].args._types[0], transferManagerKey); assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ''), "GeneralTransferManager"); @@ -671,7 +668,7 @@ contract('SecurityToken', accounts => { it("Should change the budget of the module", async() => { let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, (100 * Math.pow(10, 18)),{ from : token_owner}); - assert.equal(tx.logs[1].args._moduleType, stoKey); + assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); assert.equal(tx.logs[1].args._module, I_CappedSTO.address); assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); }); @@ -702,13 +699,14 @@ contract('SecurityToken', accounts => { // Jump time await increaseTime(5000); // Fallback transaction + console.log("BEFORE"); await web3.eth.sendTransaction({ from: account_investor1, to: I_CappedSTO.address, gas: 2100000, value: web3.utils.toWei('1', 'ether') }); - + console.log("AFTER"); assert.equal( (await I_CappedSTO.getRaised.call(0)) .dividedBy(new BigNumber(10).pow(18)) @@ -742,7 +740,7 @@ contract('SecurityToken', accounts => { let errorThrown = false; // Add permission to the deletgate (A regesteration process) await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, {from: token_owner}); - let moduleData = await I_SecurityToken.modules(permissionManagerKey, 0); + let moduleData = (await I_SecurityToken.getModulesByType(permissionManagerKey))[0]; I_GeneralPermissionManager = GeneralPermissionManager.at(moduleData); try { await I_GeneralPermissionManager.addPermission(account_delegate, delegateDetails, { from: account_temp }); @@ -1108,15 +1106,14 @@ contract('SecurityToken', accounts => { it("Should check that the list of investors is correct", async ()=> { // Hardcode list of expected accounts based on transfers above - let investorsLength = await I_SecurityToken.getInvestorsLength(); - console.log(JSON.stringify(investorsLength)); + + let investors = await I_SecurityToken.getInvestors(); let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1, account_temp]; - assert.equal(investorsLength.toNumber(), 4); - console.log("Total Seen Investors: " + investorsLength.toNumber()); - for (let i = 0; i < investorsLength.toNumber(); i++) { - let investor = await I_SecurityToken.investors(i); - assert.equal(investor, expectedAccounts[i]); + for (let i = 0; i < expectedAccounts.length; i++) { + assert.equal(investors[i], expectedAccounts[i]); } + assert.equal(investors.length, 4); + console.log("Total Seen Investors: " + investors.length); }); it("Should fail to set controller status because msg.sender not owner", async() => { let errorThrown = false; @@ -1157,7 +1154,7 @@ contract('SecurityToken', accounts => { it("Should force burn the tokens - value too high", async ()=> { let errorThrown = false; await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); - let currentInvestorCount = await I_SecurityToken.investorCount(); + let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); try { let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance + web3.utils.toWei("500", "ether"), "", { from: account_controller }); @@ -1171,7 +1168,7 @@ contract('SecurityToken', accounts => { it("Should force burn the tokens - wrong caller", async ()=> { let errorThrown = false; await I_GeneralTransferManager.changeAllowAllBurnTransfers(true, {from : token_owner}); - let currentInvestorCount = await I_SecurityToken.investorCount(); + let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); try { let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", { from: token_owner }); @@ -1184,13 +1181,13 @@ contract('SecurityToken', accounts => { }); it("Should burn the tokens", async ()=> { - let currentInvestorCount = await I_SecurityToken.investorCount(); + let currentInvestorCount = await I_SecurityToken.getInvestorCount.call(); let currentBalance = await I_SecurityToken.balanceOf(account_temp); // console.log(currentInvestorCount.toString(), currentBalance.toString()); let tx = await I_SecurityToken.forceBurn(account_temp, currentBalance, "", { from: account_controller }); // console.log(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); assert.equal(tx.logs[0].args._value.toNumber(), currentBalance.toNumber()); - let newInvestorCount = await I_SecurityToken.investorCount(); + let newInvestorCount = await I_SecurityToken.getInvestorCount.call(); // console.log(newInvestorCount.toString()); assert.equal(newInvestorCount.toNumber() + 1, currentInvestorCount.toNumber(), "Investor count drops by one"); }); @@ -1198,14 +1195,13 @@ contract('SecurityToken', accounts => { it("Should prune investor length", async ()=> { await I_SecurityToken.pruneInvestors(0, 10, {from: token_owner}); // Hardcode list of expected accounts based on transfers above - let investorsLength = (await I_SecurityToken.getInvestorsLength.call()).toNumber(); + + let investors = await I_SecurityToken.getInvestors.call(); let expectedAccounts = [account_affiliate1, account_affiliate2, account_investor1]; - assert.equal(investorsLength, 3); - console.log("Total Seen Investors: " + investorsLength); - for (let i = 0; i < investorsLength; i++) { - let investor = await I_SecurityToken.investors(i); - assert.equal(investor, expectedAccounts[i]); + for (let i = 0; i < expectedAccounts.length; i++) { + assert.equal(investors[i], expectedAccounts[i]); } + assert.equal(investors.length, 3); }); it("Should check the balance of investor at checkpoint", async() => { @@ -1302,13 +1298,13 @@ contract('SecurityToken', accounts => { let sender = account_investor1; let receiver = account_investor2; - let start_investorCount = await I_SecurityToken.investorCount.call(); + let start_investorCount = await I_SecurityToken.getInvestorCount.call(); let start_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); let start_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); let tx = await I_SecurityToken.forceTransfer(account_investor1, account_investor2, web3.utils.toWei("10", "ether"), "reason", {from: account_controller}); - let end_investorCount = await I_SecurityToken.investorCount.call(); + let end_investorCount = await I_SecurityToken.getInvestorCount.call(); let end_balInv1 = await I_SecurityToken.balanceOf.call(account_investor1); let end_balInv2 = await I_SecurityToken.balanceOf.call(account_investor2); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 1acc0ef7d..20656b0bc 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -363,12 +363,12 @@ contract('USDTieredSTO', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), TMKEY); + assert.equal(log.args._types[0].toNumber(), TMKEY); assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(TMKEY, 0); + let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -401,7 +401,7 @@ contract('USDTieredSTO', accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._type, STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); @@ -447,7 +447,7 @@ contract('USDTieredSTO', accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._type, STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); @@ -493,7 +493,7 @@ contract('USDTieredSTO', accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._type, STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); }); @@ -523,7 +523,7 @@ contract('USDTieredSTO', accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._type, STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); }); @@ -3493,7 +3493,7 @@ contract('USDTieredSTO', accounts => { describe("Test cases for the USDTieredSTOFactory", async() => { it("should get the exact details of the factory", async() => { assert.equal((await I_USDTieredSTOFactory.setupCost.call()).toNumber(), STOSetupCost); - assert.equal(await I_USDTieredSTOFactory.getType.call(),3); + assert.equal((await I_USDTieredSTOFactory.getTypes.call())[0],3); assert.equal(web3.utils.hexToString(await I_USDTieredSTOFactory.getName.call()), "USDTieredSTO", "Wrong Module added"); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index cd00ccb8d..96015926d 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -336,12 +336,12 @@ contract('USDTieredSTO Sim', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), TMKEY); + assert.equal(log.args._types[0].toNumber(), TMKEY); assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(TMKEY, 0); + let moduleData = (await I_SecurityToken.getModulesByType(TMKEY))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -379,7 +379,7 @@ contract('USDTieredSTO Sim', accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER, gasPrice: GAS_PRICE }); console.log(" Gas addModule: ".grey+tx.receipt.gasUsed.toString().grey); - assert.equal(tx.logs[2].args._type, STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); I_USDTieredSTO_Array.push(USDTieredSTO.at(tx.logs[2].args._module)); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index f01a36436..569534cad 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -247,12 +247,12 @@ contract('Concurrent STO', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(transferManagerKey, 0); + let moduleData = (await I_SecurityToken.getModulesByType(transferManagerKey))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); @@ -300,21 +300,21 @@ contract('Concurrent STO', accounts => { case 0: // Capped STO let tx1 = await I_SecurityToken.addModule(I_CappedSTOFactory.address, cappedBytesSig, maxCost, budget, { from: account_issuer }); - assert.equal(tx1.logs[3].args._type, stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(tx1.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); assert.equal(web3.utils.hexToString(tx1.logs[3].args._name),"CappedSTO",`Wrong STO module added at index ${STOIndex}`); I_STO_Array.push(CappedSTO.at(tx1.logs[3].args._module)); break; case 1: // Dummy STO let tx2 = await I_SecurityToken.addModule(I_DummySTOFactory.address, dummyBytesSig, maxCost, budget, { from: account_issuer }); - assert.equal(tx2.logs[3].args._type, stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(tx2.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); assert.equal(web3.utils.hexToString(tx2.logs[3].args._name),"DummySTO",`Wrong STO module added at index ${STOIndex}`); I_STO_Array.push(DummySTO.at(tx2.logs[3].args._module)); break; case 2: // Pre Sale STO let tx3 = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, presaleBytesSig, maxCost, budget, { from: account_issuer }); - assert.equal(tx3.logs[3].args._type, stoKey, `Wrong module type added at index ${STOIndex}`); + assert.equal(tx3.logs[3].args._types[0], stoKey, `Wrong module type added at index ${STOIndex}`); assert.equal(web3.utils.hexToString(tx3.logs[3].args._name),"PreSaleSTO",`Wrong STO module added at index ${STOIndex}`); I_STO_Array.push(PreSaleSTO.at(tx3.logs[3].args._module)); break; diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index 4db50ca9f..f4dee4bf2 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -490,7 +490,7 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); let tx = await I_SecurityToken1.addModule(I_USDTieredSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER1 }); - assert.equal(tx.logs[2].args._type, STOKEY, "USDTieredSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "USDTieredSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"USDTieredSTO","USDTieredSTOFactory module was not added"); I_USDTieredSTO = USDTieredSTO.at(tx.logs[2].args._module); }); @@ -517,14 +517,14 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [fundRaiseType], fundsReceiver]); let tx = await I_SecurityToken2.addModule(I_UpgradedCappedSTOFactory.address, bytesSTO, 0, 0, { from: ISSUER2 }); - assert.equal(tx.logs[2].args._type, STOKEY, "CappedSTO doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0], STOKEY, "CappedSTO doesn't get deployed"); assert.equal(web3.utils.hexToString(tx.logs[2].args._name),"CappedSTO","CappedSTOFactory module was not added"); }); // Attach ManualApprovalTransferManager module for TOK2 it("Should successfully attach the ManualApprovalTransferManagerFactory with the second token", async () => { const tx = await I_SecurityToken2.addModule(I_ManualApprovalTransferManagerFactory.address, "", 0, 0, { from: ISSUER2 }); - assert.equal(tx.logs[2].args._type.toNumber(), TMKEY, "ManualApprovalTransferManagerFactory doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), TMKEY, "ManualApprovalTransferManagerFactory doesn't get deployed"); assert.equal(web3.utils.toUtf8(tx.logs[2].args._name), "ManualApprovalTransferManager", "ManualApprovalTransferManagerFactory module was not added"); I_ManualApprovalTransferManagerFactory = ManualApprovalTransferManagerFactory.at(tx.logs[2].args._module); }); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 2666f7158..7032337f7 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -196,7 +196,7 @@ contract ("SecurityTokenRegistryProxy", accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); + assert.equal(log.args._types[0].toNumber(), transferManagerKey); assert.equal(web3.utils.hexToString(log.args._name),"GeneralTransferManager"); }); }) diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 95f3303ae..4330616ea 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -237,7 +237,7 @@ contract('TrackedRedemption', accounts => { const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), 2); + assert.equal(log.args._types[0].toNumber(), 2); assert.equal( web3.utils.toAscii(log.args._name) .replace(/\u0000/g, ''), @@ -246,14 +246,14 @@ contract('TrackedRedemption', accounts => { }); it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(2, 0); + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); it("Should successfully attach the TrackedRedemption with the security token", async () => { const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._type.toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); + assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); assert.equal( web3.utils.toAscii(tx.logs[2].args._name) .replace(/\u0000/g, ''), @@ -354,7 +354,7 @@ contract('TrackedRedemption', accounts => { describe("Test cases for the TrackedRedemptionFactory", async() => { it("should get the exact details of the factory", async() => { assert.equal((await I_TrackedRedemptionFactory.setupCost.call()).toNumber(), 0); - assert.equal(await I_TrackedRedemptionFactory.getType.call(), 5); + assert.equal((await I_TrackedRedemptionFactory.getTypes.call())[0], 5); assert.equal(web3.utils.toAscii(await I_TrackedRedemptionFactory.getName.call()) .replace(/\u0000/g, ''), "TrackedRedemption",