diff --git a/CHANGELOG.md b/CHANGELOG.md index b767eef56..045db881c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,9 +24,10 @@ All notable changes to this project will be documented in this file. ## Fixed * Generalize the STO varaible names and added them in `ISTO.sol` to use the common standard in all STOs. * Generalize the event when any new token get registered with the polymath ecosystem. `LogNewSecurityToken` should emit _ticker, _name, _securityTokenAddress, _owner, _addedAt, _registrant respectively. #230 - -## Removed -* Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 + +## Removed +* Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 +* Remove `Log` prefix from all the event present in the ecosystem. ====== diff --git a/contracts/FeatureRegistry.sol b/contracts/FeatureRegistry.sol index c282edb29..936a19976 100644 --- a/contracts/FeatureRegistry.sol +++ b/contracts/FeatureRegistry.sol @@ -10,7 +10,7 @@ contract FeatureRegistry is IFeatureRegistry, ReclaimTokens { mapping (bytes32 => bool) public featureStatus; - event LogChangeFeatureStatus(string _nameKey, bool _newStatus); + event ChangeFeatureStatus(string _nameKey, bool _newStatus); /** * @notice Get the status of a feature @@ -31,7 +31,7 @@ contract FeatureRegistry is IFeatureRegistry, ReclaimTokens { function setFeatureStatus(string _nameKey, bool _newStatus) public onlyOwner { bytes32 key = keccak256(bytes(_nameKey)); require(featureStatus[key] != _newStatus, "Status unchanged"); - emit LogChangeFeatureStatus(_nameKey, _newStatus); + emit ChangeFeatureStatus(_nameKey, _newStatus); featureStatus[key] = _newStatus; } diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 9878da565..94878303d 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -3,198 +3,320 @@ pragma solidity ^0.4.24; import "./interfaces/IModuleRegistry.sol"; import "./interfaces/IModuleFactory.sol"; import "./interfaces/ISecurityTokenRegistry.sol"; +import "./interfaces/IPolymathRegistry.sol"; import "./interfaces/IFeatureRegistry.sol"; -import "./Pausable.sol"; -import "./RegistryUpdater.sol"; -import "./ReclaimTokens.sol"; +import "./interfaces/IERC20.sol"; +import "./libraries/VersionUtils.sol"; +import "./storage/EternalStorage.sol"; +import "./libraries/Encoder.sol"; +import "./interfaces/IOwnable.sol"; +import "./interfaces/ISecurityToken.sol"; /** * @title Registry contract to store registered modules -* @notice Anyone can register modules, but only those "approved" by Polymath will be available for issuers to add +* @notice Only Polymath can register and verify module factories to make them available for issuers to attach. */ -contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTokens { - - // Mapping used to hold the type of module factory corresponds to the address of the Module factory contract - mapping (address => uint8) public registry; - // Mapping used to hold the reputation of the factory - mapping (address => address[]) public reputation; - // Mapping contain the list of addresses of Module factory for a particular type - mapping (uint8 => address[]) public moduleList; - // Mapping to store the index of the moduleFactory in the moduleList - mapping(address => uint8) private moduleListIndex; - // contains the list of verified modules - mapping (address => bool) public verified; - // Contains the list of the available tags corresponds to the module type - mapping (uint8 => bytes32[]) public availableTags; - - // Emit when Module been used by the securityToken - event LogModuleUsed(address indexed _moduleFactory, address indexed _securityToken); - // Emit when the Module Factory get registered with the ModuleRegistry contract - event LogModuleRegistered(address indexed _moduleFactory, address indexed _owner); - // Emit when the module get verified by the Polymath team - event LogModuleVerified(address indexed _moduleFactory, bool _verified); - // Emit when a moduleFactory is removed by Polymath or moduleFactory owner - event LogModuleRemoved(address indexed _moduleFactory, address indexed _decisionMaker); - - constructor (address _polymathRegistry) public - RegistryUpdater(_polymathRegistry) +contract ModuleRegistry is IModuleRegistry, EternalStorage { + /* + // Mapping used to hold the type of module factory corresponds to the address of the Module factory contract + mapping (address => uint8) public registry; + + // Mapping used to hold the reputation of the factory + mapping (address => address[]) public reputation; + + // Mapping containing the list of addresses of Module Factories of a particular type + mapping (uint8 => address[]) public moduleList; + + // Mapping to store the index of the Module Factory in the moduleList + mapping(address => uint8) private moduleListIndex; + + // contains the list of verified modules + mapping (address => bool) public verified; + + // Contains the list of the available tags corresponding to each module type + mapping (uint8 => bytes32[]) public availableTags; + */ + + /////////// + // Events + ////////// + + // Emit when network becomes paused + event Pause(uint256 _timestammp); + // Emit when network becomes unpaused + event Unpause(uint256 _timestamp); + // Emit when Module is used by the SecurityToken + event ModuleUsed(address indexed _moduleFactory, address indexed _securityToken); + // Emit when the Module Factory gets registered on the ModuleRegistry contract + event ModuleRegistered(address indexed _moduleFactory, address indexed _owner); + // Emit when the module gets verified by Polymath + event ModuleVerified(address indexed _moduleFactory, bool _verified); + // Emit when a ModuleFactory is removed by Polymath + event ModuleRemoved(address indexed _moduleFactory, address indexed _decisionMaker); + + /////////////// + //// Modifiers + /////////////// + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == getAddress(Encoder.getKey("owner"))); + _; + } + + /** + * @notice Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!getBool(Encoder.getKey("paused")), "Already paused"); + _; + } + + /** + * @notice Modifier to make a function callable only when the contract is paused. + */ + modifier whenPaused() { + require(getBool(Encoder.getKey("paused")), "Should not be paused"); + _; + } + + ///////////////////////////// + // Initialization + ///////////////////////////// + + // Constructor + constructor () public { + + } + + function initialize(address _polymathRegistry, address _owner) external payable { + require(!getBool(Encoder.getKey("initialised"))); + require(_owner != address(0) && _polymathRegistry != address(0), "0x address is in-valid"); + set(Encoder.getKey("polymathRegistry"), _polymathRegistry); + set(Encoder.getKey("owner"), _owner); + set(Encoder.getKey("initialised"), true); } /** - * @notice Called by a security token to check if the ModuleFactory is verified or appropriate custom module - * @dev ModuleFactory reputation increases by one every time it is deployed + * @notice Called by a SecurityToken to check if the ModuleFactory is verified or appropriate custom module + * @dev ModuleFactory reputation increases by one every time it is deployed(used) by a ST. * @dev Any module can be added during token creation without being registered if it is defined in the token proxy deployment contract * @dev The feature switch for custom modules is labelled "customModulesAllowed" * @param _moduleFactory is the address of the relevant module factory */ function useModule(address _moduleFactory) external { // This if statement is required to be able to add modules from the token proxy contract during deployment - if (ISecurityTokenRegistry(securityTokenRegistry).isSecurityToken(msg.sender)) { - if (IFeatureRegistry(featureRegistry).getFeatureStatus("customModulesAllowed")) { - require(verified[_moduleFactory]||(Ownable(_moduleFactory).owner() == Ownable(msg.sender).owner()), - "ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); + if (ISecurityTokenRegistry(getAddress(Encoder.getKey('securityTokenRegistry'))).isSecurityToken(msg.sender)) { + if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { + require(getBool(Encoder.getKey('verified', _moduleFactory)) || IOwnable(_moduleFactory).owner() == IOwnable(msg.sender).owner(), + "ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); } else { - require(verified[_moduleFactory], "ModuleFactory must be verified"); + require(getBool(Encoder.getKey('verified', _moduleFactory)), "ModuleFactory must be verified"); } - require(registry[_moduleFactory] != 0, "ModuleFactory type should not be 0"); - reputation[_moduleFactory].push(msg.sender); - emit LogModuleUsed(_moduleFactory, msg.sender); + uint8[] memory _latestVersion = ISecurityToken(msg.sender).getVersion(); + uint8[] memory _lowerBound = IModuleFactory(_moduleFactory).getLowerSTVersionBounds(); + uint8[] memory _upperBound = IModuleFactory(_moduleFactory).getUpperSTVersionBounds(); + require(VersionUtils.compareLowerBound(_lowerBound, _latestVersion), "Version should not be below the lower bound of ST version requirement"); + require(VersionUtils.compareUpperBound(_upperBound, _latestVersion), "Version should not be above the upper bound of ST version requirement"); + require(getUint(Encoder.getKey('registry',_moduleFactory)) != 0, "ModuleFactory type should not be 0"); + pushArray(Encoder.getKey('reputation', _moduleFactory), msg.sender); + emit ModuleUsed(_moduleFactory, msg.sender); } } /** - * @notice Called by moduleFactory owner to register new modules for SecurityToken to use + * @notice Called by the ModuleFactory owner to register new modules for SecurityTokens to use * @param _moduleFactory is the address of the module factory to be registered - * @return bool */ - function registerModule(address _moduleFactory) external whenNotPaused returns(bool) { - require(registry[_moduleFactory] == 0, "Module factory should not be pre-registered"); + function registerModule(address _moduleFactory) external whenNotPaused { + 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"); - registry[_moduleFactory] = moduleType; - moduleListIndex[_moduleFactory] = uint8(moduleList[moduleType].length); - moduleList[moduleType].push(_moduleFactory); - reputation[_moduleFactory] = new address[](0); - emit LogModuleRegistered (_moduleFactory, Ownable(_moduleFactory).owner()); - return true; + 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); + emit ModuleRegistered (_moduleFactory, IOwnable(_moduleFactory).owner()); } /** - * @notice Called by moduleFactory owner or registry curator to delete a moduleFactory - * @param _moduleFactory is the address of the module factory to be deleted - * @return bool + * @notice Called by the ModuleFactory owner or registry curator to delete a ModuleFactory from the registry + * @param _moduleFactory is the address of the module factory to be deleted from the registry */ - function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { - uint8 moduleType = registry[_moduleFactory]; + function removeModule(address _moduleFactory) external whenNotPaused { + uint256 moduleType = getUint(Encoder.getKey('registry', _moduleFactory)); require(moduleType != 0, "Module factory should be registered"); - require(msg.sender == Ownable(_moduleFactory).owner() || msg.sender == owner, - "msg.sender must be moduleFactory owner or registry curator"); + require(msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), + "msg.sender must be the Module Factory owner or registry curator"); - uint8 index = moduleListIndex[_moduleFactory]; - uint8 last = uint8(moduleList[moduleType].length - 1); - address temp = moduleList[moduleType][last]; + uint256 index = getUint(Encoder.getKey('moduleListIndex', _moduleFactory)); + uint256 last = getArrayAddress(Encoder.getKey('moduleList', moduleType)).length - 1; + address temp = getArrayAddress(Encoder.getKey('moduleList', moduleType))[last]; // pop from array and re-order if (index != last) { - moduleList[moduleType][index] = temp; - moduleListIndex[temp] = index; + // moduleList[moduleType][index] = temp; + setArrayIndexValue(Encoder.getKey('moduleList', moduleType), index, temp); + set(Encoder.getKey('moduleListIndex', temp), index); } - delete moduleList[moduleType][last]; - moduleList[moduleType].length--; + deleteArrayAddress(Encoder.getKey('moduleList', moduleType), last); - delete registry[_moduleFactory]; - delete reputation[_moduleFactory]; - delete verified[_moduleFactory]; - delete moduleListIndex[_moduleFactory]; - - emit LogModuleRemoved (_moduleFactory, msg.sender); - return true; + // delete registry[_moduleFactory]; + set(Encoder.getKey('registry', _moduleFactory), uint256(0)); + // delete reputation[_moduleFactory]; + setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); + // delete verified[_moduleFactory]; + set(Encoder.getKey('verified', _moduleFactory), false); + // delete moduleListIndex[_moduleFactory]; + set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(0)); + emit ModuleRemoved(_moduleFactory, msg.sender); } /** - * @notice Called by Polymath to verify modules for SecurityToken to use. + * @notice Called by Polymath to verify Module Factories for SecurityTokens to use. * @notice A module can not be used by an ST unless first approved/verified by Polymath * @notice (The only exception to this is that the author of the module is the owner of the ST) - * @param _moduleFactory is the address of the module factory to be registered + * @notice -> Only if Polymath enabled the feature. + * @param _moduleFactory is the address of the module factory to be verified * @return bool */ function verifyModule(address _moduleFactory, bool _verified) external onlyOwner returns(bool) { - //Must already have been registered - require(registry[_moduleFactory] != 0, "Module factory should have been already registered"); - verified[_moduleFactory] = _verified; - emit LogModuleVerified(_moduleFactory, _verified); + require(getUint(Encoder.getKey('registry', _moduleFactory)) != uint256(0), "Module factory must be registered"); + set(Encoder.getKey('verified', _moduleFactory), _verified); + emit ModuleVerified(_moduleFactory, _verified); return true; } /** - * @notice Add the tag for specified Module Factory - * @param _moduleType Type of module. - * @param _tag List of tags + * @notice Adds a list of tags for the specified Module Factory + * @dev This function is susceptible to hit the block gas limit if too many tags get added. + * @param _moduleType is the module type. + * @param _tag is the list of tags to add. */ function addTagByModuleType(uint8 _moduleType, bytes32[] _tag) external onlyOwner { for (uint8 i = 0; i < _tag.length; i++) { - availableTags[_moduleType].push(_tag[i]); + pushArray(Encoder.getKey('availableTags', uint256(_moduleType)), _tag[i]); } } /** - * @notice remove the tag for specified Module Factory - * @param _moduleType Type of module. - * @param _removedTags List of tags + * @notice Removes the tag for specified Module Factory + * @dev This function is susceptible to hit the block gas limit if too many tags get removed. + * @param _moduleType is the module type. + * @param _removedTags is the list of tags to remove */ function removeTagByModuleType(uint8 _moduleType, bytes32[] _removedTags) external onlyOwner { - for (uint8 i = 0; i < availableTags[_moduleType].length; i++) { + for (uint8 i = 0; i < getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType))).length; i++) { for (uint8 j = 0; j < _removedTags.length; j++) { - if (availableTags[_moduleType][i] == _removedTags[j]) { - delete availableTags[_moduleType][i]; + if (getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType)))[i] == _removedTags[j]) { + deleteArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType)), uint256(i)); } } } } /** - * @notice Use to get all the tags releated to the functionality of the Module Factory. - * @param _moduleType Type of module + * @notice Returns all the tags related to the functionality of the entered Module Factory. + * @param _moduleType is the module type * @return bytes32 array */ function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]) { - return availableTags[_moduleType]; + return getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType))); } /** - * @notice Use to get the reputation of the Module factory - * @param _factoryAddress Ethereum contract address of the module factory - * @return address array which have the list of securityToken's uses that module factory + * @notice Returns the reputation of the entered Module Factory + * @param _factoryAddress is the address of the module factory + * @return address array which contains the list of securityTokens that use that module factory */ function getReputationOfFactory(address _factoryAddress) external view returns(address[]) { - return reputation[_factoryAddress]; + return getArrayAddress(Encoder.getKey('reputation', _factoryAddress)); } /** - * @notice Use to get the list of addresses of Module factory for a particular type + * @notice Returns the list of addresses of Module Factory of a particular type * @param _moduleType Type of Module - * @return address array thal contains the lis of addresses of module factory contracts. + * @return address array that contains the list of addresses of module factory contracts. */ function getModuleListOfType(uint8 _moduleType) external view returns(address[]) { - return moduleList[_moduleType]; + return getArrayAddress(Encoder.getKey('moduleList', uint256(_moduleType))); } /** - * @notice pause registration function + * @notice Returns the list of available Module factory addresses of a particular type for a given token. + * @param _moduleType is the module type to look for + * @param _securityToken is the address of SecurityToken + * @return address array that contains the list of available addresses of module factory contracts. */ - function unpause() public onlyOwner { - _unpause(); + function getAvailableModulesOfType(uint8 _moduleType, address _securityToken) external view returns (address[]) { + uint256 _len = getArrayAddress(Encoder.getKey('moduleList', uint256(_moduleType))).length; + address[] memory _addressList = getArrayAddress(Encoder.getKey('moduleList', uint256(_moduleType))); + uint256 counter = 0; + for (uint256 i = 0; i < _len; i++) { + if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { + if (IOwnable(_addressList[i]).owner() == IOwnable(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[i]))) + counter++; + } + else if (getBool(Encoder.getKey('verified', _addressList[i]))) { + counter ++; + } + } + address[] memory _tempArray = new address[](counter); + counter = 0; + for (uint256 j = 0; j < _len; j++) { + if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { + if (IOwnable(_addressList[j]).owner() == IOwnable(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[j]))) { + _tempArray[counter] = _addressList[j]; + counter ++; + } + } + else if (getBool(Encoder.getKey('verified', _addressList[j]))) { + _tempArray[counter] = _addressList[j]; + counter ++; + } + } + return _tempArray; } /** - * @notice unpause registration function + * @notice Reclaim all ERC20Basic compatible tokens + * @param _tokenContract The address of the token contract + */ + function reclaimERC20(address _tokenContract) external onlyOwner { + require(_tokenContract != address(0)); + IERC20 token = IERC20(_tokenContract); + uint256 balance = token.balanceOf(address(this)); + require(token.transfer(getAddress(Encoder.getKey("owner")), balance)); + } + + /** + * @notice Called by the owner to pause, triggers stopped state */ - function pause() public onlyOwner { - _pause(); + function pause() external whenNotPaused onlyOwner { + set(Encoder.getKey("paused"), true); + emit Pause(now); } + /** + * @notice Called by the owner to unpause, returns to normal state + */ + function unpause() external whenPaused onlyOwner { + set(Encoder.getKey("paused"), false); + emit Unpause(now); + } + + /** + * @notice Stores the contract addresses of other key contracts from the PolymathRegistry + */ + function updateFromRegistry() onlyOwner external { + address _polymathRegistry = getAddress(Encoder.getKey('polymathRegistry')); + set(Encoder.getKey('securityTokenRegistry'), IPolymathRegistry(_polymathRegistry).getAddress("SecurityTokenRegistry")); + set(Encoder.getKey('featureRegistry'), IPolymathRegistry(_polymathRegistry).getAddress("FeatureRegistry")); + set(Encoder.getKey('polyToken'), IPolymathRegistry(_polymathRegistry).getAddress("PolyToken")); + } } diff --git a/contracts/PolymathRegistry.sol b/contracts/PolymathRegistry.sol index 847659b81..d33ad68f4 100644 --- a/contracts/PolymathRegistry.sol +++ b/contracts/PolymathRegistry.sol @@ -9,14 +9,14 @@ contract PolymathRegistry is ReclaimTokens { mapping (bytes32 => address) public storedAddresses; - event LogChangeAddress(string _nameKey, address indexed _oldAddress, address indexed _newAddress); + event ChangeAddress(string _nameKey, address indexed _oldAddress, address indexed _newAddress); /** * @notice Get the contract address * @param _nameKey is the key for the contract address mapping * @return address */ - function getAddress(string _nameKey) view public returns(address) { + function getAddress(string _nameKey) view external returns(address) { bytes32 key = keccak256(bytes(_nameKey)); require(storedAddresses[key] != address(0), "Invalid address key"); return storedAddresses[key]; @@ -27,9 +27,9 @@ contract PolymathRegistry is ReclaimTokens { * @param _nameKey is the key for the contract address mapping * @param _newAddress is the new contract address */ - function changeAddress(string _nameKey, address _newAddress) public onlyOwner { + function changeAddress(string _nameKey, address _newAddress) external onlyOwner { bytes32 key = keccak256(bytes(_nameKey)); - emit LogChangeAddress(_nameKey, storedAddresses[key], _newAddress); + emit ChangeAddress(_nameKey, storedAddresses[key], _newAddress); storedAddresses[key] = _newAddress; } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 11fd36498..9a4e66b0b 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -8,6 +8,7 @@ import "./interfaces/ISecurityTokenRegistry.sol"; import "./storage/EternalStorage.sol"; import "./libraries/Util.sol"; import "./libraries/Encoder.sol"; +import "./libraries/VersionUtils.sol"; /** * @title Registry contract for issuers to register their tickers and security tokens @@ -21,6 +22,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { uint256 public stLaunchFee; uint256 public tickerRegFee; uint256 public expiryLimit; + uint256 public latestProtocolVersion; bool public paused; address public owner; address public polymathRegistry; @@ -34,6 +36,13 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { mapping(string => TickerDetails) registeredTickers; mapping(address => SecurityTokenData) securityTokens; mapping(bytes32 => address) protocolVersionST; + mapping(uint256 => ProtocolVersion) versionData; + + struct ProtocolVersion { + uint8 major; + uint8 minor; + uint8 patch; + } struct TickerDetails { address owner; @@ -58,21 +67,21 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { // Emit when network becomes unpaused event Unpause(uint256 _timestamp); // Emit when the ticker is removed from the registry - event LogTickerRemoved(string _ticker, uint256 _removedAt, address _removedBy); + event TickerRemoved(string _ticker, uint256 _removedAt, address _removedBy); // Emit when the token ticker expiry is changed - event LogChangeExpiryLimit(uint256 _oldExpiry, uint256 _newExpiry); + event ChangeExpiryLimit(uint256 _oldExpiry, uint256 _newExpiry); // Emit when changeSecurityLaunchFee is called - event LogChangeSecurityLaunchFee(uint256 _oldFee, uint256 _newFee); + event ChangeSecurityLaunchFee(uint256 _oldFee, uint256 _newFee); // Emit when changeTickerRegistrationFee is called - event LogChangeTickerRegistrationFee(uint256 _oldFee, uint256 _newFee); + event ChangeTickerRegistrationFee(uint256 _oldFee, uint256 _newFee); // Emit when ownership gets transferred event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // Emit when ownership of the ticker gets changed - event LogChangeTickerOwnership(string _ticker, address indexed _oldOwner, address indexed _newOwner); + event ChangeTickerOwnership(string _ticker, address indexed _oldOwner, address indexed _newOwner); // Emit when a ticker details is modified - event LogModifyTickerDetails(address _owner, string _ticker, string _name, uint256 _registrationDate, uint256 _expiryDate, bool _status); + event ModifyTickerDetails(address _owner, string _ticker, string _name, uint256 _registrationDate, uint256 _expiryDate, bool _status); // Emit at the time of launching a new security token - event LogNewSecurityToken( + event NewSecurityToken( string _ticker, string _name, address indexed _securityTokenAddress, @@ -82,7 +91,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bool _fromAdmin ); // Emit after ticker registration - event LogRegisterTicker( + event RegisterTicker( address indexed _owner, string _ticker, string _name, @@ -146,11 +155,11 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("polyToken"), _polyToken); set(Encoder.getKey("stLaunchFee"), _stLaunchFee); set(Encoder.getKey("tickerRegFee"), _tickerRegFee); - set(Encoder.getKey("expiryLimit"), uint256(15 * 1 days)); + set(Encoder.getKey("expiryLimit"), uint256(60 * 1 days)); set(Encoder.getKey("paused"), false); set(Encoder.getKey("owner"), _owner); set(Encoder.getKey("polymathRegistry"), _polymathRegistry); - _setProtocolVersion(_STFactory, "0.0.1"); + _setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(2)); set(Encoder.getKey("initialised"), true); } @@ -218,7 +227,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); } _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit LogRegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, true); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, true); } /** @@ -232,7 +241,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _deleteTickerOwnership(owner, ticker); set(Encoder.getKey("tickerToSecurityToken", ticker), address(0)); _storeTickerDetails(ticker, address(0), 0, 0, "", false); - emit LogTickerRemoved(_ticker, now, msg.sender); + emit TickerRemoved(_ticker, now, msg.sender); } /** @@ -256,7 +265,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { function _addTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status, bool _fromAdmin) internal { _setTickerOwner(_owner, _ticker); _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit LogRegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin); } /** @@ -312,7 +321,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { function _transferTickerOwnership(address _oldOwner, address _newOwner, string _ticker) internal { _deleteTickerOwnership(_oldOwner, _ticker); _setTickerOwner(_newOwner, _ticker); - emit LogChangeTickerOwnership(_ticker, _oldOwner, _newOwner); + emit ChangeTickerOwnership(_ticker, _oldOwner, _newOwner); } /** @@ -336,7 +345,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { require(_newExpiry >= 1 days, "Expiry should >= 1 day"); - emit LogChangeExpiryLimit(getUint(Encoder.getKey('expiryLimit')), _newExpiry); + emit ChangeExpiryLimit(getUint(Encoder.getKey('expiryLimit')), _newExpiry); set(Encoder.getKey('expiryLimit'), _newExpiry); } @@ -444,7 +453,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(getAddress(Encoder.getKey("registeredTickers_owner", ticker)) == msg.sender, "Ticker and token should have same owner"); require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker should not have expired"); - set(Encoder.getKey("registeredTickers_status", _ticker), true); + set(Encoder.getKey("registeredTickers_status", ticker), true); if (getUint(Encoder.getKey("stLaunchFee")) > 0) require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), getUint(Encoder.getKey("stLaunchFee"))), "Sufficent allowance is not provided"); @@ -461,7 +470,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _storeSecurityTokenData(newSecurityTokenAddress, ticker, _tokenDetails, now); set(Encoder.getKey("tickerToSecurityToken", ticker), newSecurityTokenAddress); - emit LogNewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false); + emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false); } /** @@ -483,7 +492,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _modifyTicker(_owner, ticker, _name, getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)), true); set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); - emit LogNewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true); + emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true); } /** @@ -567,7 +576,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { require(getUint(Encoder.getKey('tickerRegFee')) != _tickerRegFee); - emit LogChangeTickerRegistrationFee(getUint(Encoder.getKey('tickerRegFee')), _tickerRegFee); + emit ChangeTickerRegistrationFee(getUint(Encoder.getKey('tickerRegFee')), _tickerRegFee); set(Encoder.getKey('tickerRegFee'), _tickerRegFee); } @@ -577,7 +586,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { require(getUint(Encoder.getKey("stLaunchFee")) != _stLaunchFee); - emit LogChangeSecurityLaunchFee(getUint(Encoder.getKey("stLaunchFee")), _stLaunchFee); + emit ChangeSecurityLaunchFee(getUint(Encoder.getKey("stLaunchFee")), _stLaunchFee); set(Encoder.getKey("stLaunchFee"), _stLaunchFee); } @@ -597,25 +606,40 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions * @notice Changing versions does not affect existing tokens. * @param _STFactoryAddress is the address of the proxy. - * @param _version is the new version of the proxy which is used to deploy the security token. + * @param _major Major version of the proxy. + * @param _minor Minor version of the proxy. + * @param _patch Patch version of the proxy */ - function setProtocolVersion(address _STFactoryAddress, bytes32 _version) external onlyOwner { - _setProtocolVersion(_STFactoryAddress, _version); + function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { + _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); } /** * @notice Internal - Changes the protocol version and the SecurityToken contract */ - function _setProtocolVersion(address _STFactoryAddress, bytes32 _version) internal { - set(Encoder.getKey("protocolVersion"), _version); - set(Encoder.getKey("protocolVersionST", getBytes32(Encoder.getKey("protocolVersion"))), _STFactoryAddress); + function _setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) internal { + uint8[] memory _version = new uint8[](3); + _version[0] = _major; + _version[1] = _minor; + _version[2] = _patch; + uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); + require(VersionUtils.isValidVersion(getProtocolVersion(), _version),"In-valid version"); + set(Encoder.getKey("latestVersion"), uint256(_packedVersion)); + set(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))), _STFactoryAddress); } /** * @notice Returns the current STFactory Address */ function getSTFactoryAddress() public view returns(address) { - return getAddress(Encoder.getKey("protocolVersionST", getBytes32(Encoder.getKey("protocolVersion")))); + return getAddress(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion")))); + } + + /** + * @notice get Protocol version + */ + function getProtocolVersion() public view returns(uint8[]) { + return VersionUtils.unpack(uint24(getUint(Encoder.getKey("latestVersion")))); } /** diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 54028a614..38f2a9e0d 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -5,10 +5,10 @@ pragma solidity ^0.4.24; */ interface IModuleFactory { - event LogChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); - event LogChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); - event LogChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); - event LogGenerateModuleFromFactory( + event ChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); + event ChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); + event ChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); + event GenerateModuleFromFactory( address _module, bytes32 indexed _moduleName, address indexed _moduleFactory, @@ -16,6 +16,7 @@ interface IModuleFactory { uint256 _setupCost, uint256 _timestamp ); + event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); //Should create an instance of the Module, or throw function deploy(bytes _data) external returns(address); @@ -73,9 +74,28 @@ interface IModuleFactory { */ function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) external; + /** + * @notice Function use to change the lower and upper bound of the compatible version st + * @param _boundType Type of bound + * @param _newVersion new version array + */ + function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external; + /** * @notice Get the setup cost of the module */ function getSetupCost() external view returns (uint256); + /** + * @notice use to get the lower bound + * @return lower bound + */ + function getLowerSTVersionBounds() external view returns(uint8[]); + + /** + * @notice use to get the upper bound + * @return upper bound + */ + function getUpperSTVersionBounds() external view returns(uint8[]); + } diff --git a/contracts/interfaces/IModuleRegistry.sol b/contracts/interfaces/IModuleRegistry.sol index 972b1dc9f..59763bd57 100644 --- a/contracts/interfaces/IModuleRegistry.sol +++ b/contracts/interfaces/IModuleRegistry.sol @@ -15,14 +15,13 @@ interface IModuleRegistry { * @notice Called by the ModuleFactory owner to register new modules for SecurityToken to use * @param _moduleFactory is the address of the module factory to be registered */ - function registerModule(address _moduleFactory) external returns(bool); + function registerModule(address _moduleFactory) external; /** * @notice Called by the ModuleFactory owner or registry curator to delete a ModuleFactory * @param _moduleFactory is the address of the module factory to be deleted - * @return bool */ - function removeModule(address _moduleFactory) external returns(bool); + function removeModule(address _moduleFactory) external; /** * @notice Use to get all the tags releated to the functionality of the Module Factory. @@ -67,4 +66,17 @@ interface IModuleRegistry { */ function getModuleListOfType(uint8 _moduleType) external view returns(address[]); + /** + * @notice Use to get the list of available Module factory addresses for a particular type + * @param _moduleType Type of Module + * @param _securityToken Address of securityToken + * @return address array that contains the list of available addresses of module factory contracts. + */ + function getAvailableModulesOfType(uint8 _moduleType, address _securityToken) external view returns (address[]); + + /** + * @notice Use to get the latest contract address of the regstries + */ + function updateFromRegistry() external; + } diff --git a/contracts/interfaces/IPolymathRegistry.sol b/contracts/interfaces/IPolymathRegistry.sol new file mode 100644 index 000000000..cb2de8d02 --- /dev/null +++ b/contracts/interfaces/IPolymathRegistry.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.24; + + +interface IPolymathRegistry { + + /** + * @notice Get the contract address + * @param _nameKey is the key for the contract address mapping + * @return address + */ + function getAddress(string _nameKey) view external returns(address); + +} + \ No newline at end of file diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index 6628361b4..33e38201c 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -231,4 +231,9 @@ interface ISecurityToken { * @dev enabled via feature switch "disableControllerAllowed" */ function disableController() external; + + /** + * @notice Use to get the version of the securityToken + */ + function getVersion() external view returns(uint8[]); } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index b76b22ea9..444fb5375 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -39,10 +39,12 @@ interface ISecurityTokenRegistry { * @notice Changes the protocol version and the SecurityToken contract * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions * @notice Changing versions does not affect existing tokens. - * @param _STFactoryAddress is the address of the ST Factory - * @param _version is the version name of the ST + * @param _STFactoryAddress Address of the proxy. + * @param _major Major version of the proxy. + * @param _minor Minor version of the proxy. + * @param _patch Patch version of the proxy */ - function setProtocolVersion(address _STFactoryAddress, bytes32 _version) external; + function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external; /** * @notice Check that Security Token is registered @@ -79,6 +81,11 @@ interface ISecurityTokenRegistry { */ function getSTFactoryAddress() external view returns(address); + /** + * @notice get Protocol version + */ + function getProtocolVersion() public view returns(uint8[]); + /** * @notice Use to get the ticker list as per the owner * @param _owner Address which owns the list of tickers diff --git a/contracts/interfaces/IUSDTieredSTOProxy.sol b/contracts/interfaces/IUSDTieredSTOProxy.sol new file mode 100644 index 000000000..1f0526d5d --- /dev/null +++ b/contracts/interfaces/IUSDTieredSTOProxy.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.4.24; + +/** + * @title Interface for security token proxy deployment + */ +interface IUSDTieredSTOProxy { + + /** + * @notice deploys the STO. + * @param _securityToken Contract address of the securityToken + * @param _polyAddress Contract address of the PolyToken. + * @param _factoryAddress Contract address of the factory + * @return address Address of the deployed STO + */ + function deploySTO(address _securityToken, address _polyAddress, address _factoryAddress) external returns (address); + + /** + * @notice Use to get the init function signature + * @param _contractAddress Address of the STO contract + * @return bytes4 + */ + function getInitFunction(address _contractAddress) external returns (bytes4); + +} \ No newline at end of file diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol new file mode 100644 index 000000000..9b5f4fcc4 --- /dev/null +++ b/contracts/libraries/VersionUtils.sol @@ -0,0 +1,134 @@ +pragma solidity ^0.4.24; + +/** + * @title Helper library use to compare or validate the semantic versions + */ + +library VersionUtils { + + /** + * @notice This function is used to validate the version submitted + * @param _current Array holds the present version of ST + * @param _new Array holds the latest version of the ST + * @return bool + */ + function isValidVersion(uint8[] _current, uint8[] _new) internal pure returns(bool) { + bool[] memory _temp = new bool[](_current.length); + uint8 counter = 0; + for (uint8 i = 0; i < _current.length; i++) { + if (_current[i] < _new[i]) + _temp[i] = true; + else + _temp[i] = false; + } + + for (i = 0; i < _current.length; i++) { + if (i == 0) { + if (_current[i] <= _new[i]) + if(_temp[0]) { + counter = counter + 3; + break; + } else + counter++; + else + return false; + } else { + if (_temp[i-1]) + counter++; + else if (_current[i] <= _new[i]) + counter++; + else + return false; + } + } + if (counter == _current.length) + return true; + } + + /** + * @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 + */ + function compareLowerBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { + require(_version1.length == _version2.length); + uint counter = 0; + for (uint8 j = 0; j< _version1.length; j++) { + if (_version1[j] == 0) + counter ++; + } + if (counter != _version1.length) { + counter = 0; + for (uint8 i = 0; i < _version1.length; i++) { + if (_version2[i] > _version1[i]) + return true; + else if (_version2[i] < _version1[i]) + return false; + else + counter++; + } + if (counter == _version1.length - 1) + return true; + else + return false; + } else + 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 + */ + function compareUpperBound(uint8[] _version1, uint8[] _version2) internal pure returns(bool) { + require(_version1.length == _version2.length); + uint counter = 0; + for (uint8 j = 0; j< _version1.length; j++) { + if (_version1[j] == 0) + counter ++; + } + if (counter != _version1.length) { + counter = 0; + for (uint8 i = 0; i < _version1.length; i++) { + if (_version1[i] > _version2[i]) + return true; + else if (_version1[i] < _version2[i]) + return false; + else + counter++; + } + if (counter == _version1.length - 1) + return true; + else + return false; + } else + return true; + } + + + /** + * @notice Use to pack the uint8[] array data into uint24 value + * @param _major Major version + * @param _minor Minor version + * @param _patch Patch version + */ + function pack(uint8 _major, uint8 _minor, uint8 _patch) internal pure returns(uint24) { + return (uint24(_major) << 16) | (uint24(_minor) << 8) | uint24(_patch); + } + + /** + * @notice Use to convert packed data into uint8 array + * @param _packedVersion Packed data + */ + function unpack(uint24 _packedVersion) internal pure returns (uint8[]) { + uint8[] memory _unpackVersion = new uint8[](3); + _unpackVersion[0] = uint8(_packedVersion >> 16); + _unpackVersion[1] = uint8(_packedVersion >> 8); + _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 f1840a793..2f7772d77 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -17,6 +17,8 @@ contract MockFactory is ModuleFactory { name = "Mock"; title = "Mock Manager"; description = "MockManager"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/mocks/ModuleRegistryMock.sol b/contracts/mocks/ModuleRegistryMock.sol new file mode 100644 index 000000000..18551dd20 --- /dev/null +++ b/contracts/mocks/ModuleRegistryMock.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.4.24; + +import "../ModuleRegistry.sol"; + +/** + * @title Registry contract for issuers to register their security tokens + */ +contract ModuleRegistryMock is ModuleRegistry { + + /// @notice It is dummy functionality + /// Alert! Alert! Do not use it for the mainnet release + function addMoreTags(uint8 _moduleType, bytes32[] _tag) public onlyOwner { + for (uint8 i = 0; i < _tag.length; i++) { + pushArray(Encoder.getKey('availableTags', uint256(_moduleType)), _tag[i]); + } + } + +} \ No newline at end of file diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index 683a336dc..71521e242 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -17,6 +17,8 @@ contract TestSTOFactory is ModuleFactory { name = "TestSTO"; title = "Test STO"; description = "Test STO"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index d2abf4443..d789ad5e3 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -22,6 +22,8 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { 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)); } /** @@ -32,7 +34,7 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { 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 LogGenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(erc20DividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return erc20DividendCheckpoint; } diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 90e816d43..146691d82 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -22,6 +22,8 @@ contract EtherDividendCheckpointFactory is ModuleFactory { 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)); } /** @@ -32,7 +34,7 @@ contract EtherDividendCheckpointFactory is ModuleFactory { 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 LogGenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(ethDividendCheckpoint, getName(), address(this), msg.sender, setupCost, now); return ethDividendCheckpoint; } diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index 8e8a6a5e1..66ffc822d 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.24; import "../interfaces/IERC20.sol"; import "../interfaces/IModuleFactory.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "../libraries/VersionUtils.sol"; /** * @title Interface that any module factory contract should implement @@ -19,10 +20,18 @@ contract ModuleFactory is IModuleFactory, Ownable { bytes32 public name; string public title; - event LogChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); - event LogChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); - event LogChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); - event LogGenerateModuleFromFactory(address _module, bytes32 indexed _moduleName, address indexed _moduleFactory, address _creator, uint256 _timestamp); + // @notice Allow only two variables to store + // 1. lowerBound + // 2. upperBound + // @dev (0.0.0 will act as the wildcard) + // @dev uint24 consists packed value of uint8 _major, uint8 _minor, uint8 _patch + mapping(string => uint24) compatibleSTVersionRange; + + event ChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory); + event ChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory); + event ChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory); + event GenerateModuleFromFactory(address _module, bytes32 indexed _moduleName, address indexed _moduleFactory, address _creator, uint256 _timestamp); + event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); /** * @notice Constructor @@ -40,7 +49,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _newSetupCost new setup cost */ function changeFactorySetupFee(uint256 _newSetupCost) public onlyOwner { - emit LogChangeFactorySetupFee(setupCost, _newSetupCost, address(this)); + emit ChangeFactorySetupFee(setupCost, _newSetupCost, address(this)); setupCost = _newSetupCost; } @@ -49,7 +58,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _newUsageCost new usage cost */ function changeFactoryUsageFee(uint256 _newUsageCost) public onlyOwner { - emit LogChangeFactoryUsageFee(usageCost, _newUsageCost, address(this)); + emit ChangeFactoryUsageFee(usageCost, _newUsageCost, address(this)); usageCost = _newUsageCost; } @@ -58,7 +67,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _newSubscriptionCost new subscription cost */ function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) public onlyOwner { - emit LogChangeFactorySubscriptionFee(monthlySubscriptionCost, _newSubscriptionCost, address(this)); + emit ChangeFactorySubscriptionFee(monthlySubscriptionCost, _newSubscriptionCost, address(this)); monthlySubscriptionCost = _newSubscriptionCost; } @@ -99,4 +108,37 @@ contract ModuleFactory is IModuleFactory, Ownable { version = _newVersion; } + /** + * @notice Function use to change the lower and upper bound of the compatible version st + * @param _boundType Type of bound + * @param _newVersion new version array + */ + function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external onlyOwner { + require(keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("lowerBound")) || keccak256(abi.encodePacked(_boundType)) == keccak256(abi.encodePacked("upperBound")), + "Must be a valid bound type"); + require(_newVersion.length == 3); + if (compatibleSTVersionRange[_boundType] != uint24(0)) { + uint8[] memory _currentVersion = VersionUtils.unpack(compatibleSTVersionRange[_boundType]); + require(VersionUtils.isValidVersion(_currentVersion, _newVersion), "Failed because of in-valid version"); + } + compatibleSTVersionRange[_boundType] = VersionUtils.pack(_newVersion[0], _newVersion[1], _newVersion[2]); + emit ChangeSTVersionBound(_boundType, _newVersion[0], _newVersion[1], _newVersion[2]); + } + + /** + * @notice use to get the lower bound + * @return lower bound + */ + function getLowerSTVersionBounds() external view returns(uint8[]) { + return VersionUtils.unpack(compatibleSTVersionRange["lowerBound"]); + } + + /** + * @notice use to get the upper bound + * @return upper bound + */ + function getUpperSTVersionBounds() external view returns(uint8[]) { + return VersionUtils.unpack(compatibleSTVersionRange["upperBound"]); + } + } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManager.sol b/contracts/modules/PermissionManager/GeneralPermissionManager.sol index 1550289ee..c11806344 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManager.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManager.sol @@ -16,9 +16,9 @@ contract GeneralPermissionManager is IPermissionManager, Module { bytes32 public constant CHANGE_PERMISSION = "CHANGE_PERMISSION"; /// Event emitted after any permission get changed for the delegate - event LogChangePermission(address _delegate, address _module, bytes32 _perm, bool _valid, uint256 _timestamp); + event ChangePermission(address _delegate, address _module, bytes32 _perm, bool _valid, uint256 _timestamp); /// Use to notify when delegate is added in permission manager contract - event LogAddPermission(address _delegate, bytes32 _details, uint256 _timestamp); + event AddPermission(address _delegate, bytes32 _details, uint256 _timestamp); /// @notice constructor constructor (address _securityToken, address _polyAddress) public @@ -55,7 +55,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { */ function addPermission(address _delegate, bytes32 _details) public withPerm(CHANGE_PERMISSION) { delegateDetails[_delegate] = _details; - emit LogAddPermission(_delegate, _details, now); + emit AddPermission(_delegate, _details, now); } /** @@ -78,7 +78,7 @@ contract GeneralPermissionManager is IPermissionManager, Module { { require(delegateDetails[_delegate] != bytes32(0), "Delegate details not set"); perms[_module][_delegate][_perm] = _valid; - emit LogChangePermission(_delegate, _module, _perm, _valid, now); + emit ChangePermission(_delegate, _module, _perm, _valid, now); return true; } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index b6bb29677..e6e6e65a1 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -19,6 +19,8 @@ contract GeneralPermissionManagerFactory is ModuleFactory { name = "GeneralPermissionManager"; title = "General Permission Manager"; description = "Manage permissions within the Security Token and attached modules"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -29,7 +31,7 @@ contract GeneralPermissionManagerFactory is ModuleFactory { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address permissionManager = new GeneralPermissionManager(msg.sender, address(polyToken)); - emit LogGenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(permissionManager), getName(), address(this), msg.sender, setupCost, now); return permissionManager; } diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index d47fca382..982f790f0 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -20,6 +20,8 @@ contract CappedSTOFactory is ModuleFactory { name = "CappedSTO"; title = "Capped STO"; description = "Use to collects the funds and once the cap is reached then investment will be no longer entertained"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -34,7 +36,7 @@ contract CappedSTOFactory is ModuleFactory { //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == cappedSTO.getInitFunction(), "Invalid data"); require(address(cappedSTO).call(_data), "Unsuccessfull call"); - emit LogGenerateModuleFromFactory(address(cappedSTO), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(cappedSTO), getName(), address(this), msg.sender, setupCost, now); return address(cappedSTO); } diff --git a/contracts/modules/STO/DummySTO.sol b/contracts/modules/STO/DummySTO.sol index d030b7611..8e7640d94 100644 --- a/contracts/modules/STO/DummySTO.sol +++ b/contracts/modules/STO/DummySTO.sol @@ -15,7 +15,7 @@ contract DummySTO is ISTO { uint256 public cap; string public someString; - event LogGenerateTokens(address _investor, uint256 _amount); + event GenerateTokens(address _investor, uint256 _amount); mapping (address => uint256) public investors; @@ -64,7 +64,7 @@ contract DummySTO is ISTO { } //TODO: Add SafeMath maybe investors[_investor] = investors[_investor] + _amount; - emit LogGenerateTokens (_investor, _amount); + emit GenerateTokens (_investor, _amount); } /** diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index d34ef8b38..ec249b420 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -20,6 +20,8 @@ contract DummySTOFactory is ModuleFactory { name = "DummySTO"; title = "Dummy STO"; description = "Dummy STO"; + 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 @@ -33,7 +35,7 @@ contract DummySTOFactory is ModuleFactory { //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == dummySTO.getInitFunction(), "Invalid data"); require(address(dummySTO).call(_data), "Unsuccessfull call"); - emit LogGenerateModuleFromFactory(address(dummySTO), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(dummySTO), getName(), address(this), msg.sender, setupCost, now); return address(dummySTO); } diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index bb4163ecc..03ca13bbe 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -20,6 +20,8 @@ contract PreSaleSTOFactory is ModuleFactory { name = "PreSaleSTO"; title = "PreSale STO"; description = "Allows Issuer to configure pre-sale token allocations"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -36,7 +38,7 @@ contract PreSaleSTOFactory is ModuleFactory { //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == preSaleSTO.getInitFunction(), "Invalid data"); require(address(preSaleSTO).call(_data), "Unsuccessfull call"); - emit LogGenerateModuleFromFactory(address(preSaleSTO), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(preSaleSTO), getName(), address(this), msg.sender, setupCost, now); return address(preSaleSTO); } diff --git a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol new file mode 100644 index 000000000..dc4d6c628 --- /dev/null +++ b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.4.24; + +import "../USDTieredSTO.sol"; +import "../../../interfaces/IUSDTieredSTOProxy.sol"; + +contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { + + + + constructor() public { + + } + + /** + * @notice deploys the STO. + * @param _securityToken Contract address of the securityToken + * @param _polyAddress Contract address of the PolyToken. + * @param _factoryAddress Contract address of the factory + * @return address Address of the deployed STO + */ + function deploySTO(address _securityToken, address _polyAddress, address _factoryAddress) external returns (address) { + address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _polyAddress, _factoryAddress); + return newSecurityTokenAddress; + } + + /** + * @notice Use to get the init function signature + * @param _contractAddress Address of the STO contract + * @return bytes4 + */ + function getInitFunction(address _contractAddress) external returns (bytes4) { + return USDTieredSTO(_contractAddress).getInitFunction(); + } +} \ No newline at end of file diff --git a/contracts/modules/STO/USDTieredSTO.sol b/contracts/modules/STO/USDTieredSTO.sol index 16113c188..86687eb58 100644 --- a/contracts/modules/STO/USDTieredSTO.sol +++ b/contracts/modules/STO/USDTieredSTO.sol @@ -141,9 +141,11 @@ contract USDTieredSTO is ISTO, ReentrancyGuard { // STO Configuration // /////////////////////// - constructor (address _securityToken, address _polyAddress) public Module(_securityToken, _polyAddress) { + constructor (address _securityToken, address _polyAddress, address _factory) public Module(_securityToken, _polyAddress) { oracleKeys[bytes32("ETH")][bytes32("USD")] = ETH_ORACLE; oracleKeys[bytes32("POLY")][bytes32("USD")] = POLY_ORACLE; + require(_factory != address(0), "In-valid address"); + factory = _factory; } /** diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4e0c134da..1b01cec66 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./USDTieredSTO.sol"; +import "../../interfaces/IUSDTieredSTOProxy.sol"; import "../ModuleFactory.sol"; import "../../libraries/Util.sol"; @@ -9,17 +9,23 @@ import "../../libraries/Util.sol"; */ contract USDTieredSTOFactory is ModuleFactory { + address public USDTieredSTOProxyAddress; + /** * @notice Constructor * @param _polyAddress Address of the polytoken */ - constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost, address _proxyFactoryAddress) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) - { + { + require(_proxyFactoryAddress != address(0), "0x address is not allowed"); + USDTieredSTOProxyAddress = _proxyFactoryAddress; version = "1.0.0"; name = "USDTieredSTO"; title = "USD Tiered STO"; description = "USD Tiered STO"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -29,13 +35,15 @@ contract USDTieredSTOFactory is ModuleFactory { function deploy(bytes _data) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); + require(USDTieredSTOProxyAddress != address(0), "Proxy contract should be pre-set"); //Check valid bytes - can only call module init function - USDTieredSTO usdTieredSTO = new USDTieredSTO(msg.sender, address(polyToken)); + address usdTieredSTO = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, address(polyToken), address(this)); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == usdTieredSTO.getInitFunction(), "Invalid data"); + require(Util.getSig(_data) == IUSDTieredSTOProxy(USDTieredSTOProxyAddress).getInitFunction(usdTieredSTO), "Invalid data"); require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); - emit LogGenerateModuleFromFactory(address(usdTieredSTO), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, setupCost, now); return address(usdTieredSTO); + // return 0xca35b7d915458ef540ade6068dfe2f44e8fa733c; } /** diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index 3f07d32e1..274dae2d8 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -12,7 +12,7 @@ contract CountTransferManager is ITransferManager { bytes32 public constant ADMIN = "ADMIN"; - event LogModifyHolderCount(uint256 _oldHolderCount, uint256 _newHolderCount); + event ModifyHolderCount(uint256 _oldHolderCount, uint256 _newHolderCount); /** * @notice Constructor @@ -60,7 +60,7 @@ contract CountTransferManager is ITransferManager { * @param _maxHolderCount is the new maximum amount a holder can hold */ function changeHolderCount(uint256 _maxHolderCount) public withPerm(ADMIN) { - emit LogModifyHolderCount(maxHolderCount, _maxHolderCount); + emit ModifyHolderCount(maxHolderCount, _maxHolderCount); maxHolderCount = _maxHolderCount; } diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index 3e88f4b7e..aa7d2cda2 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -20,6 +20,8 @@ contract CountTransferManagerFactory is ModuleFactory { name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -33,7 +35,7 @@ contract CountTransferManagerFactory is ModuleFactory { CountTransferManager countTransferManager = new CountTransferManager(msg.sender, address(polyToken)); require(Util.getSig(_data) == countTransferManager.getInitFunction(), "Provided data is not valid"); require(address(countTransferManager).call(_data), "Un-successfull call"); - emit LogGenerateModuleFromFactory(address(countTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(countTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(countTransferManager); } diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 2014e8c06..3cd7e9152 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -41,19 +41,19 @@ contract GeneralTransferManager is ITransferManager { bool public allowAllBurnTransfers = false; // Emit when Issuance address get changed - event LogChangeIssuanceAddress(address _issuanceAddress); + event ChangeIssuanceAddress(address _issuanceAddress); // Emit when there is change in the flag variable called allowAllTransfers - event LogAllowAllTransfers(bool _allowAllTransfers); + event AllowAllTransfers(bool _allowAllTransfers); // Emit when there is change in the flag variable called allowAllWhitelistTransfers - event LogAllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers); + event AllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers); // Emit when there is change in the flag variable called allowAllWhitelistIssuances - event LogAllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances); + event AllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances); // Emit when there is change in the flag variable called allowAllBurnTransfers - event LogAllowAllBurnTransfers(bool _allowAllBurnTransfers); + event AllowAllBurnTransfers(bool _allowAllBurnTransfers); // Emit when there is change in the flag variable called signingAddress - event LogChangeSigningAddress(address _signingAddress); + event ChangeSigningAddress(address _signingAddress); // Emit when investor details get modified related to their whitelisting - event LogModifyWhitelist( + event ModifyWhitelist( address _investor, uint256 _dateAdded, address _addedBy, @@ -87,7 +87,7 @@ contract GeneralTransferManager is ITransferManager { */ function changeIssuanceAddress(address _issuanceAddress) public withPerm(FLAGS) { issuanceAddress = _issuanceAddress; - emit LogChangeIssuanceAddress(_issuanceAddress); + emit ChangeIssuanceAddress(_issuanceAddress); } /** @@ -96,7 +96,7 @@ contract GeneralTransferManager is ITransferManager { */ function changeSigningAddress(address _signingAddress) public withPerm(FLAGS) { signingAddress = _signingAddress; - emit LogChangeSigningAddress(_signingAddress); + emit ChangeSigningAddress(_signingAddress); } /** @@ -107,7 +107,7 @@ contract GeneralTransferManager is ITransferManager { */ function changeAllowAllTransfers(bool _allowAllTransfers) public withPerm(FLAGS) { allowAllTransfers = _allowAllTransfers; - emit LogAllowAllTransfers(_allowAllTransfers); + emit AllowAllTransfers(_allowAllTransfers); } /** @@ -118,7 +118,7 @@ contract GeneralTransferManager is ITransferManager { */ function changeAllowAllWhitelistTransfers(bool _allowAllWhitelistTransfers) public withPerm(FLAGS) { allowAllWhitelistTransfers = _allowAllWhitelistTransfers; - emit LogAllowAllWhitelistTransfers(_allowAllWhitelistTransfers); + emit AllowAllWhitelistTransfers(_allowAllWhitelistTransfers); } /** @@ -129,7 +129,7 @@ contract GeneralTransferManager is ITransferManager { */ function changeAllowAllWhitelistIssuances(bool _allowAllWhitelistIssuances) public withPerm(FLAGS) { allowAllWhitelistIssuances = _allowAllWhitelistIssuances; - emit LogAllowAllWhitelistIssuances(_allowAllWhitelistIssuances); + emit AllowAllWhitelistIssuances(_allowAllWhitelistIssuances); } /** @@ -140,7 +140,7 @@ contract GeneralTransferManager is ITransferManager { */ function changeAllowAllBurnTransfers(bool _allowAllBurnTransfers) public withPerm(FLAGS) { allowAllBurnTransfers = _allowAllBurnTransfers; - emit LogAllowAllBurnTransfers(_allowAllBurnTransfers); + emit AllowAllBurnTransfers(_allowAllBurnTransfers); } /** @@ -188,7 +188,7 @@ contract GeneralTransferManager is ITransferManager { function modifyWhitelist(address _investor, uint256 _fromTime, uint256 _toTime, uint256 _expiryTime, bool _canBuyFromSTO) public withPerm(WHITELIST) { //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); - emit LogModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** @@ -246,7 +246,7 @@ contract GeneralTransferManager is ITransferManager { _checkSig(hash, _v, _r, _s); //Passing a _time == 0 into this function, is equivalent to removing the _investor from the whitelist whitelist[_investor] = TimeRestriction(_fromTime, _toTime, _expiryTime, _canBuyFromSTO); - emit LogModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); + emit ModifyWhitelist(_investor, now, msg.sender, _fromTime, _toTime, _expiryTime, _canBuyFromSTO); } /** diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4a15c47dc..a3490130b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -19,6 +19,8 @@ contract GeneralTransferManagerFactory is ModuleFactory { name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } @@ -30,7 +32,7 @@ contract GeneralTransferManagerFactory is ModuleFactory { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address generalTransferManager = new GeneralTransferManager(msg.sender, address(polyToken)); - emit LogGenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(generalTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(generalTransferManager); } diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index 9fb5a247f..04629995a 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -34,7 +34,7 @@ contract ManualApprovalTransferManager is ITransferManager { //Store mappings of address => address with ManualBlockings mapping (address => mapping (address => ManualBlocking)) public manualBlockings; - event LogAddManualApproval( + event AddManualApproval( address _from, address _to, uint256 _allowance, @@ -42,20 +42,20 @@ contract ManualApprovalTransferManager is ITransferManager { address _addedBy ); - event LogAddManualBlocking( + event AddManualBlocking( address _from, address _to, uint256 _expiryTime, address _addedBy ); - event LogRevokeManualApproval( + event RevokeManualApproval( address _from, address _to, address _addedBy ); - event LogRevokeManualBlocking( + event RevokeManualBlocking( address _from, address _to, address _addedBy @@ -118,7 +118,7 @@ contract ManualApprovalTransferManager is ITransferManager { require(_expiryTime > now, "Invalid expiry time"); require(manualApprovals[_from][_to].allowance == 0, "Approval already exists"); manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime); - emit LogAddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); + emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender); } /** @@ -133,7 +133,7 @@ contract ManualApprovalTransferManager is ITransferManager { require(_expiryTime > now, "Invalid expiry time"); require(manualApprovals[_from][_to].expiryTime == 0, "Blocking already exists"); manualBlockings[_from][_to] = ManualBlocking(_expiryTime); - emit LogAddManualBlocking(_from, _to, _expiryTime, msg.sender); + emit AddManualBlocking(_from, _to, _expiryTime, msg.sender); } /** @@ -145,7 +145,7 @@ contract ManualApprovalTransferManager is ITransferManager { require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); delete manualApprovals[_from][_to]; - emit LogRevokeManualApproval(_from, _to, msg.sender); + emit RevokeManualApproval(_from, _to, msg.sender); } /** @@ -157,7 +157,7 @@ contract ManualApprovalTransferManager is ITransferManager { require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); delete manualBlockings[_from][_to]; - emit LogRevokeManualBlocking(_from, _to, msg.sender); + emit RevokeManualBlocking(_from, _to, msg.sender); } /** diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 00621fd36..2c0e60eb5 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -22,6 +22,8 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -32,7 +34,7 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { if (setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); address manualTransferManager = new ManualApprovalTransferManager(msg.sender, address(polyToken)); - emit LogGenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(manualTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(manualTransferManager); } diff --git a/contracts/modules/TransferManager/PercentageTransferManager.sol b/contracts/modules/TransferManager/PercentageTransferManager.sol index ef7bd0ce7..805d04557 100644 --- a/contracts/modules/TransferManager/PercentageTransferManager.sol +++ b/contracts/modules/TransferManager/PercentageTransferManager.sol @@ -18,8 +18,8 @@ contract PercentageTransferManager is ITransferManager { // Addresses on this list are always able to send / receive tokens mapping (address => bool) public whitelist; - event LogModifyHolderPercentage(uint256 _oldHolderPercentage, uint256 _newHolderPercentage); - event LogModifyWhitelist( + event ModifyHolderPercentage(uint256 _oldHolderPercentage, uint256 _newHolderPercentage); + event ModifyWhitelist( address _investor, uint256 _dateAdded, address _addedBy, @@ -73,7 +73,7 @@ contract PercentageTransferManager is ITransferManager { * @param _maxHolderPercentage is the new maximum percentage (multiplied by 10**16) */ function changeHolderPercentage(uint256 _maxHolderPercentage) public onlyOwner { - emit LogModifyHolderPercentage(maxHolderPercentage, _maxHolderPercentage); + emit ModifyHolderPercentage(maxHolderPercentage, _maxHolderPercentage); maxHolderPercentage = _maxHolderPercentage; } @@ -84,7 +84,7 @@ contract PercentageTransferManager is ITransferManager { */ function modifyWhitelist(address _investor, bool _valid) public withPerm(WHITELIST) { whitelist[_investor] = _valid; - emit LogModifyWhitelist(_investor, now, msg.sender, _valid); + emit ModifyWhitelist(_investor, now, msg.sender, _valid); } /** diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 728681792..59949880c 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -20,6 +20,8 @@ contract PercentageTransferManagerFactory is ModuleFactory { name = "PercentageTransferManager"; title = "Percentage Transfer Manager"; description = "Restrict the number of investors"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -33,7 +35,7 @@ contract PercentageTransferManagerFactory is ModuleFactory { PercentageTransferManager percentageTransferManager = new PercentageTransferManager(msg.sender, address(polyToken)); require(Util.getSig(_data) == percentageTransferManager.getInitFunction(), "Provided data is not valid"); require(address(percentageTransferManager).call(_data), "Un-successfull call"); - emit LogGenerateModuleFromFactory(address(percentageTransferManager), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(percentageTransferManager), getName(), address(this), msg.sender, setupCost, now); return address(percentageTransferManager); } diff --git a/contracts/proxy/ModuleRegistryProxy.sol b/contracts/proxy/ModuleRegistryProxy.sol new file mode 100644 index 000000000..1c4fc945e --- /dev/null +++ b/contracts/proxy/ModuleRegistryProxy.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.4.24; + +import "../storage/EternalStorage.sol"; +import "./OwnedUpgradeabilityProxy.sol"; + + +/** + * @title ModuleRegistryProxy + * @dev This proxy holds the storage of the token contract and delegates every call to the current implementation set. + * Besides, it allows to upgrade the token's behaviour towards further implementations, and provides basic + * authorization control functionalities + */ +contract ModuleRegistryProxy is EternalStorage, OwnedUpgradeabilityProxy { + +} \ No newline at end of file diff --git a/contracts/storage/EternalStorage.sol b/contracts/storage/EternalStorage.sol index 897983c1e..d476b13bb 100644 --- a/contracts/storage/EternalStorage.sol +++ b/contracts/storage/EternalStorage.sol @@ -159,6 +159,30 @@ contract EternalStorage { uintArrayStorage[_key].push(_value); } + ///////////////////////// + //// Set Array functions + //////////////////////// + /// @notice use to intialize the array + /// Ex1- mapping (address => address[]) public reputation; + /// reputation[0x1] = new address[](0); It can be replaced as + /// setArray(hash('reputation', 0x1), new address[](0)); + + function setArray(bytes32 _key, address[] _value) internal { + addressArrayStorage[_key] = _value; + } + + function setArray(bytes32 _key, uint256[] _value) internal { + uintArrayStorage[_key] = _value; + } + + function setArray(bytes32 _key, bytes32[] _value) internal { + bytes32ArrayStorage[_key] = _value; + } + + function setArray(bytes32 _key, string[] _value) internal { + stringArrayStorage[_key] = _value; + } + ///////////////////////// /// getArray functions ///////////////////////// @@ -184,6 +208,29 @@ contract EternalStorage { return uintArrayStorage[_key]; } + /////////////////////////////////// + /// setArrayIndexValue() functions + /////////////////////////////////// + /// @notice set the value of particular index of the address array + /// Ex1- mapping(bytes32 => address[]) moduleList; + /// general way is -- moduleList[moduleType][index] = temp; + /// It can be re-write as -- setArrayIndexValue(keccak256(abi.encodePacked('moduleList', moduleType)), index, temp); + + function setArrayIndexValue(bytes32 _key, uint256 _index, address _value) internal { + addressArrayStorage[_key][_index] = _value; + } + + function setArrayIndexValue(bytes32 _key, uint256 _index, uint256 _value) internal { + uintArrayStorage[_key][_index] = _value; + } + + function setArrayIndexValue(bytes32 _key, uint256 _index, bytes32 _value) internal { + bytes32ArrayStorage[_key][_index] = _value; + } + + function setArrayIndexValue(bytes32 _key, uint256 _index, string _value) internal { + stringArrayStorage[_key][_index] = _value; + } ///////////////////////////// /// Public getters functions diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 86f761854..f8d91c389 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -28,7 +28,14 @@ import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol"; contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, RegistryUpdater { using SafeMath for uint256; - bytes32 public constant securityTokenVersion = "0.0.2"; + // Use to hold the version + struct SemanticVersion { + uint8 major; + uint8 minor; + uint8 patch; + } + + SemanticVersion public securityTokenVersion; // off-chain hash string public tokenDetails; @@ -94,7 +101,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr mapping (address => bool) public investorListed; // Emit at the time when module get added - event LogModuleAdded( + event ModuleAdded( uint8 indexed _type, bytes32 _name, address _moduleFactory, @@ -105,33 +112,33 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr ); // Emit when the token details get updated - event LogUpdateTokenDetails(string _oldDetails, string _newDetails); + event UpdateTokenDetails(string _oldDetails, string _newDetails); // Emit when the granularity get changed - event LogGranularityChanged(uint256 _oldGranularity, uint256 _newGranularity); + event GranularityChanged(uint256 _oldGranularity, uint256 _newGranularity); // Emit when Module get removed from the securityToken - event LogModuleRemoved(uint8 indexed _type, address _module, uint256 _timestamp); + event ModuleRemoved(uint8 indexed _type, address _module, uint256 _timestamp); // Emit when Module get archived from the securityToken - event LogModuleArchived(uint8 indexed _type, address _module, uint256 _timestamp); + event ModuleArchived(uint8 indexed _type, address _module, uint256 _timestamp); // Emit when Module get unarchived from the securityToken - event LogModuleUnarchived(uint8 indexed _type, address _module, uint256 _timestamp); + event ModuleUnarchived(uint8 indexed _type, address _module, uint256 _timestamp); // Emit when the budget allocated to a module is changed - event LogModuleBudgetChanged(uint8 indexed _moduleType, address _module, uint256 _oldBudget, uint256 _budget); + event ModuleBudgetChanged(uint8 indexed _moduleType, address _module, uint256 _oldBudget, uint256 _budget); // Emit when transfers are frozen or unfrozen - event LogFreezeTransfers(bool _status, uint256 _timestamp); + event FreezeTransfers(bool _status, uint256 _timestamp); // Emit when new checkpoint created - event LogCheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp); + event CheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp); // Emit when is permanently frozen by the issuer - event LogFreezeMinting(uint256 _timestamp); + event FreezeMinting(uint256 _timestamp); // Change the STR address in the event of a upgrade - event LogChangeSTRAddress(address indexed _oldAddress, address indexed _newAddress); + event ChangeSTRAddress(address indexed _oldAddress, address indexed _newAddress); // Events to log minting and burning event Minted(address indexed to, uint256 amount); event Burnt(address indexed _burner, uint256 _value); // Events to log controller actions - event LogSetController(address indexed _oldController, address indexed _newController); - event LogForceTransfer(address indexed _controller, address indexed _from, address indexed _to, uint256 _amount, bool _verifyTransfer, bytes _data); - event LogDisableController(uint256 _timestamp); + event SetController(address indexed _oldController, address indexed _newController); + event ForceTransfer(address indexed _controller, address indexed _from, address indexed _to, uint256 _amount, bool _verifyTransfer, bytes _data); + event DisableController(uint256 _timestamp); function isModule(address _module, uint8 _type) internal view returns (bool) { require(modulesToData[_module].module == _module, "Address mismatch"); @@ -205,6 +212,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr updateFromRegistry(); tokenDetails = _tokenDetails; granularity = _granularity; + securityTokenVersion = SemanticVersion(0,0,2); } /** @@ -255,7 +263,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr modules[moduleType].push(module); names[moduleName].push(module); //Emit log event - emit LogModuleAdded(moduleType, moduleName, _moduleFactory, module, moduleCost, _budget, now); + emit ModuleAdded(moduleType, moduleName, _moduleFactory, module, moduleCost, _budget, now); } /** @@ -265,7 +273,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function archiveModule(address _module) external onlyOwner { require(!modulesToData[_module].isArchived, "Module not unarchived"); require(modulesToData[_module].module != address(0), "Module missing"); - emit LogModuleArchived(modulesToData[_module].moduleType, _module, now); + emit ModuleArchived(modulesToData[_module].moduleType, _module, now); modulesToData[_module].isArchived = true; } @@ -275,7 +283,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ function unarchiveModule(address _module) external onlyOwner { require(modulesToData[_module].isArchived, "Module not archived"); - emit LogModuleUnarchived(modulesToData[_module].moduleType, _module, now); + emit ModuleUnarchived(modulesToData[_module].moduleType, _module, now); modulesToData[_module].isArchived = false; } @@ -286,7 +294,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function removeModule(address _module) external onlyOwner { require(modulesToData[_module].isArchived, "Module not archived"); require(modulesToData[_module].module != address(0), "Module missing"); - emit LogModuleRemoved(modulesToData[_module].moduleType, _module, now); + emit ModuleRemoved(modulesToData[_module].moduleType, _module, now); // Remove from module type list uint256 index = modulesToData[_module].moduleIndex; uint8 moduleType = modulesToData[_module].moduleType; @@ -371,7 +379,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr } else { require(IERC20(polyToken).increaseApproval(_module, _budget.sub(_currentAllowance)), "Insufficient balance to increaseApproval"); } - emit LogModuleBudgetChanged(modulesToData[_module].moduleType, _module, _currentAllowance, _budget); + emit ModuleBudgetChanged(modulesToData[_module].moduleType, _module, _currentAllowance, _budget); } /** @@ -379,7 +387,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _newTokenDetails New token details */ function updateTokenDetails(string _newTokenDetails) external onlyOwner { - emit LogUpdateTokenDetails(tokenDetails, _newTokenDetails); + emit UpdateTokenDetails(tokenDetails, _newTokenDetails); tokenDetails = _newTokenDetails; } @@ -389,7 +397,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ function changeGranularity(uint256 _granularity) external onlyOwner { require(_granularity != 0, "Granularity can not be 0"); - emit LogGranularityChanged(granularity, _granularity); + emit GranularityChanged(granularity, _granularity); granularity = _granularity; } @@ -450,7 +458,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function freezeTransfers() external onlyOwner { require(!transfersFrozen); transfersFrozen = true; - emit LogFreezeTransfers(true, now); + emit FreezeTransfers(true, now); } /** @@ -459,7 +467,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function unfreezeTransfers() external onlyOwner { require(transfersFrozen); transfersFrozen = false; - emit LogFreezeTransfers(false, now); + emit FreezeTransfers(false, now); } /** @@ -600,7 +608,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ function freezeMinting() external isMintingAllowed() isEnabled("freezeMintingAllowed") onlyOwner { mintingFrozen = true; - emit LogFreezeMinting(now); + emit FreezeMinting(now); } /** @@ -696,7 +704,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr function createCheckpoint() external onlyModuleOrOwner(CHECKPOINT_KEY) returns(uint256) { require(currentCheckpointId < 2**256 - 1); currentCheckpointId = currentCheckpointId + 1; - emit LogCheckpointCreated(currentCheckpointId, now); + emit CheckpointCreated(currentCheckpointId, now); return currentCheckpointId; } @@ -766,7 +774,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr */ function setController(address _controller) public onlyOwner { require(!controllerDisabled); - emit LogSetController(controller, _controller); + emit SetController(controller, _controller); controller = _controller; } @@ -778,7 +786,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr require(!controllerDisabled); controllerDisabled = true; delete controller; - emit LogDisableController(now); + emit DisableController(now); } /** @@ -799,9 +807,20 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); - emit LogForceTransfer(msg.sender, _from, _to, _value, verified, _data); + emit ForceTransfer(msg.sender, _from, _to, _value, verified, _data); emit Transfer(_from, _to, _value); return true; } + /** + * @notice Use to get the version of the securityToken + */ + function getVersion() external view returns(uint8[]) { + uint8[] memory _version = new uint8[](3); + _version[0] = securityTokenVersion.major; + _version[1] = securityTokenVersion.minor; + _version[2] = securityTokenVersion.patch; + return _version; + } + } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 9f1d4d268..9b9c5eb64 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,11 +1,13 @@ -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const ManualApprovalTransferManagerFactory = artifacts.require('./ManualApprovalTransferManagerFactory.sol') const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol') const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol') @@ -103,6 +105,18 @@ module.exports = function (deployer, network, accounts) { ] }; +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 @@ -112,13 +126,16 @@ module.exports = function (deployer, network, accounts) { return polymathRegistry.changeAddress("PolyToken", PolyToken, {from: PolymathAccount}) .then(() => { // A) Deploy the ModuleRegistry Contract (It contains the list of verified ModuleFactory) - // console.log("test" + PolymathRegistry.address); - return deployer.deploy(ModuleRegistry, polymathRegistry.address, {from: PolymathAccount}); + return deployer.deploy(ModuleRegistry, {from: PolymathAccount}); + }).then(() => { + return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); }).then(() => { - return ModuleRegistry.deployed().then((_moduleRegistry) => { - moduleRegistry = _moduleRegistry; + 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", ModuleRegistry.address, {from: PolymathAccount}); + 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) @@ -232,7 +249,7 @@ module.exports = function (deployer, network, accounts) { return polymathRegistry.changeAddress("SecurityTokenRegistry", SecurityTokenRegistryProxy.address, {from: PolymathAccount}); }).then(() => { // Update all addresses into the registry contract by calling the function updateFromregistry - return ModuleRegistry.at(ModuleRegistry.address).updateFromRegistry({from: PolymathAccount}); + return moduleRegistry.updateFromRegistry({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}) @@ -245,9 +262,12 @@ module.exports = function (deployer, network, accounts) { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(CappedSTOFactory.address, true, {from: PolymathAccount}) + }).then(() => { + // Deploy the proxy factory + return deployer.deploy(USDTieredSTOProxyFactory, {from: PolymathAccount}); }).then(() => { // H) Deploy the USDTieredSTOFactory (Use to generate the USDTieredSTOFactory contract which will used to collect the funds ). - return deployer.deploy(USDTieredSTOFactory, PolyToken, usdTieredSTOSetupCost, 0, 0, {from: PolymathAccount}) + 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. @@ -269,6 +289,7 @@ module.exports = function (deployer, network, accounts) { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} ETHOracle: ${ETHOracle} @@ -280,6 +301,7 @@ module.exports = function (deployer, network, accounts) { CappedSTOFactory: ${CappedSTOFactory.address} USDTieredSTOFactory: ${USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} @@ -295,5 +317,4 @@ module.exports = function (deployer, network, accounts) { }); }); }); -}); } diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d6bc3c0ef..36f5bd41e 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -1,12 +1,13 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); const CappedSTO = artifacts.require('./CappedSTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); @@ -53,6 +54,7 @@ contract('CappedSTO', accounts => { let I_GeneralTransferManager; let I_SecurityTokenRegistry; let I_ModuleRegistry; + let I_ModuleRegistryProxy; let I_FeatureRegistry; let I_CappedSTOFactory; let I_STFactory; @@ -63,6 +65,7 @@ contract('CappedSTO', accounts => { let I_PolyToken; let I_PolymathRegistry; let I_STRProxied; + let I_MRProxied; let pauseTime; // SecurityToken Details for funds raise Type ETH @@ -90,7 +93,7 @@ contract('CappedSTO', accounts => { let endTime_ETH1; let startTime_ETH2; let endTime_ETH2; - const cap = new BigNumber(10000).times(new BigNumber(10).pow(18)); + const cap = web3.utils.toWei("10000"); const rate = 1000; const E_fundRaiseType = 0; @@ -99,36 +102,14 @@ contract('CappedSTO', accounts => { let startTime_POLY2; let endTime_POLY2; let blockNo; - const P_cap = new BigNumber(50000).times(new BigNumber(10).pow(18)); + const P_cap = web3.utils.toWei("50000"); const P_fundRaiseType = 1; const P_rate = 5; const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); const maxCost = cappedSTOSetupCost; - - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes', - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { // Accounts setup @@ -148,20 +129,25 @@ contract('CappedSTO', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 3: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -171,7 +157,7 @@ contract('CappedSTO', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 4: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -181,7 +167,7 @@ contract('CappedSTO', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 5: Deploy the CappedSTOFactory + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -191,19 +177,19 @@ contract('CappedSTO', accounts => { "CappedSTOFactory contract was not deployed" ); - // STEP 6: Register the Modules with the ModuleRegistry contract + // STEP 7: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_CappedSTOFactory.address, { from: token_owner }); - await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: token_owner }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); // Step 8: Deploy the STFactory contract @@ -215,6 +201,8 @@ contract('CappedSTO', accounts => { "STFactory contract was not deployed", ); + // Step 9: Deploy the SecurityTokenRegistry contract + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); assert.notEqual( @@ -223,30 +211,18 @@ contract('CappedSTO', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract + // Step 10: Deploy the proxy and attach the implementation contract to it. I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -254,6 +230,7 @@ contract('CappedSTO', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -286,7 +263,7 @@ contract('CappedSTO', accounts => { I_SecurityToken_ETH = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken_ETH.LogModuleAdded({from: _blockNo}), 1); + 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); @@ -315,7 +292,7 @@ contract('CappedSTO', accounts => { let endTime = startTime + duration.days(30); await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); let errorThrown = false; try { const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 26000000 }); @@ -332,7 +309,7 @@ contract('CappedSTO', accounts => { let endTime = startTime + duration.days(30); await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, 0, [E_fundRaiseType], account_fundsReceiver]); let errorThrown = false; try { const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 26000000 }); @@ -345,7 +322,7 @@ contract('CappedSTO', accounts => { }); it("Should fail to launch the STO due to startTime > endTime", async () => { - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [ Math.floor(Date.now()/1000 + 100000), Math.floor(Date.now()/1000 + 1000), cap, rate, [E_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [ Math.floor(Date.now()/1000 + 100000), Math.floor(Date.now()/1000 + 1000), cap, rate, [E_fundRaiseType], account_fundsReceiver]); let errorThrown = false; try { const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 26000000 }); @@ -360,7 +337,7 @@ contract('CappedSTO', accounts => { it("Should fail to launch the STO due to cap is of 0 securityToken", async () => { let startTime = latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [ startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [ startTime, endTime, 0, rate, [E_fundRaiseType], account_fundsReceiver]); let errorThrown = false; try { const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 26000000 }); @@ -375,7 +352,7 @@ contract('CappedSTO', accounts => { it("Should successfully attach the STO module to the security token", async () => { startTime_ETH1 = latestTime() + duration.days(1); endTime_ETH1 = startTime_ETH1 + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + 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, gas: 45000000 }); assert.equal(tx.logs[3].args._type, stoKey, "CappedSTO doesn't get deployed"); @@ -746,7 +723,7 @@ contract('CappedSTO', accounts => { await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost, { from: token_owner}); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime_ETH2, endTime_ETH2, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + 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"); @@ -855,7 +832,7 @@ contract('CappedSTO', accounts => { await I_PolyToken.getTokens(cappedSTOSetupCost*19, token_owner); await I_PolyToken.transfer(I_SecurityToken_ETH.address, cappedSTOSetupCost*19, { from: token_owner}); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], account_fundsReceiver]); for (var STOIndex = 2; STOIndex < MAX_MODULES; STOIndex++) { const tx = await I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner }); @@ -903,7 +880,7 @@ contract('CappedSTO', accounts => { I_SecurityToken_POLY = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken_POLY.LogModuleAdded({from: _blockNo}), 1); + 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); @@ -922,7 +899,7 @@ contract('CappedSTO', accounts => { await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime_POLY1, endTime_POLY1, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY1, endTime_POLY1, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 26000000 }); @@ -948,7 +925,7 @@ contract('CappedSTO', accounts => { ); assert.equal( (await I_CappedSTO_Array_POLY[0].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), - P_cap.dividedBy(new BigNumber(10).pow(18)), + BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), "STO Configuration doesn't set as expected" ); assert.equal( @@ -1280,7 +1257,7 @@ contract('CappedSTO', accounts => { await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); await I_PolyToken.transfer(I_SecurityToken_POLY.address, cappedSTOSetupCost, { from: token_owner}); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime_POLY2, endTime_POLY2, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime_POLY2, endTime_POLY2, P_cap, P_rate, [P_fundRaiseType], account_fundsReceiver]); const tx = await I_SecurityToken_POLY.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 26000000 }); @@ -1302,7 +1279,7 @@ contract('CappedSTO', accounts => { ); assert.equal( (await I_CappedSTO_Array_POLY[1].cap.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), - P_cap.dividedBy(new BigNumber(10).pow(18)), + BigNumber(P_cap).dividedBy(new BigNumber(10).pow(18)), "STO Configuration doesn't set as expected" ); assert.equal( diff --git a/test/c_checkpoints.js b/test/c_checkpoints.js index 8e3da77ee..a0355b4c7 100644 --- a/test/c_checkpoints.js +++ b/test/c_checkpoints.js @@ -5,6 +5,7 @@ import { encodeProxyCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -46,7 +47,9 @@ contract('Checkpoints', accounts => { let I_GeneralTransferManager; let I_ExchangeTransferManager; let I_STRProxied; + let I_MRProxied; let I_ModuleRegistry; + let I_ModuleRegistryProxy; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_STFactory; @@ -69,6 +72,9 @@ contract('Checkpoints', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -86,22 +92,28 @@ contract('Checkpoints', accounts => { // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - // Step 0: Deploy the token Faucet and Mint tokens for token_owner + // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 1: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + // Step 2: Deploy the FeatureRegistry - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -111,7 +123,7 @@ contract('Checkpoints', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -121,17 +133,19 @@ contract('Checkpoints', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); + // STEP 6: Register the Modules with the ModuleRegistry contract + // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // Step 7: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); assert.notEqual( I_STFactory.address.valueOf(), @@ -139,7 +153,8 @@ contract('Checkpoints', accounts => { "STFactory contract was not deployed", ); - // Deploy the SecurityTokenregistry + // Step 8: Deploy the SecurityTokenRegistry contract + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); assert.notEqual( @@ -148,29 +163,18 @@ contract('Checkpoints', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract + // Step 9: Deploy the proxy and attach the implementation contract to it. I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + // Step 10: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -178,6 +182,7 @@ contract('Checkpoints', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -207,7 +212,7 @@ contract('Checkpoints', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 6ae3c8d71..309e4bdaa 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -1,10 +1,11 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -52,6 +53,8 @@ contract('CountTransferManager', accounts => { let I_GeneralTransferManager; let I_ExchangeTransferManager; let I_ModuleRegistry; + let I_ModuleRegistryProxy; + let I_MRProxied; let I_STRProxied; let I_FeatureRegistry; let I_SecurityTokenRegistry; @@ -77,16 +80,9 @@ contract('CountTransferManager', accounts => { // CountTransferManager details const holderCount = 2; // Maximum number of token holders - - let bytesSTO = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_maxHolderCount' - } - ] - }, [holderCount]); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + let bytesSTO = encodeModuleCall(['uint256'], [holderCount]); before(async() => { // Accounts setup @@ -107,20 +103,32 @@ contract('CountTransferManager', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); assert.notEqual( - I_ModuleRegistry.address.valueOf(), + I_FeatureRegistry.address.valueOf(), "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" + "FeatureRegistry contract was not deployed", ); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -130,7 +138,7 @@ contract('CountTransferManager', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -140,7 +148,7 @@ contract('CountTransferManager', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 4: Deploy the CountTransferManager + // STEP 6: Deploy the CountTransferManager I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); assert.notEqual( I_CountTransferManagerFactory.address.valueOf(), @@ -148,7 +156,7 @@ contract('CountTransferManager', accounts => { "CountTransferManagerFactory contract was not deployed" ); - // STEP 4: Deploy Paid the CountTransferManager + // STEP 7: Deploy Paid the CountTransferManager P_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); assert.notEqual( P_CountTransferManagerFactory.address.valueOf(), @@ -156,25 +164,25 @@ contract('CountTransferManager', accounts => { "CountTransferManagerFactory contract was not deployed" ); - // STEP 5: Register the Modules with the ModuleRegistry contract + // STEP 8: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the CountTransferManagerFactory - await I_ModuleRegistry.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); // (C) : Register the Paid CountTransferManagerFactory - await I_ModuleRegistry.registerModule(P_CountTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(P_CountTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(P_CountTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_CountTransferManagerFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 9: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); @@ -184,7 +192,7 @@ contract('CountTransferManager', accounts => { "STFactory contract was not deployed", ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 10: Deploy the SecurityTokenRegistry // Deploy the SecurityTokenregistry I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -195,31 +203,19 @@ contract('CountTransferManager', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract + // Step 11: Deploy the proxy and attach the implementation contract I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); + // Step 12: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -228,6 +224,7 @@ contract('CountTransferManager', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -257,7 +254,7 @@ contract('CountTransferManager', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); @@ -454,24 +451,6 @@ contract('CountTransferManager', accounts => { ); }); - // it("Should not be able to transfer to a token holder", async() => { - // let errorThrown = false; - - // await I_CountTransferManager.pause({from: token_owner}); - // assert.isTrue(await I_CountTransferManager.paused.call()); - - // try { - // // Mint some tokens - // await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - // } catch(error) { - // console.log(`Failed due to transfers are paused`); - // ensureException(error); - // errorThrown = true; - // } - // assert.ok(errorThrown, message); - // }); - - it("Should not be able to transfer to a new token holder", async() => { let errorThrown = false; // await I_CountTransferManager.unpause({from: token_owner}); diff --git a/test/e_erc20_dividends.js b/test/e_erc20_dividends.js index 4e4812419..1ffd20041 100644 --- a/test/e_erc20_dividends.js +++ b/test/e_erc20_dividends.js @@ -5,6 +5,7 @@ import { encodeProxyCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -52,8 +53,10 @@ contract('ERC20DividendCheckpoint', accounts => { let I_ERC20DividendCheckpoint; let I_GeneralTransferManager; let I_ExchangeTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_STRProxied; + let I_MRProxied; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_STFactory; @@ -76,6 +79,8 @@ contract('ERC20DividendCheckpoint', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { // Accounts setup @@ -98,20 +103,25 @@ contract('ERC20DividendCheckpoint', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -121,7 +131,7 @@ contract('ERC20DividendCheckpoint', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -131,7 +141,7 @@ contract('ERC20DividendCheckpoint', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 4: Deploy the ERC20DividendCheckpoint + // STEP 6: Deploy the ERC20DividendCheckpoint P_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); assert.notEqual( P_ERC20DividendCheckpointFactory.address.valueOf(), @@ -139,7 +149,7 @@ contract('ERC20DividendCheckpoint', accounts => { "ERC20DividendCheckpointFactory contract was not deployed" ); - // STEP 4: Deploy the ERC20DividendCheckpoint + // STEP 7: Deploy the ERC20DividendCheckpoint I_ERC20DividendCheckpointFactory = await ERC20DividendCheckpointFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); assert.notEqual( I_ERC20DividendCheckpointFactory.address.valueOf(), @@ -147,25 +157,25 @@ contract('ERC20DividendCheckpoint', accounts => { "ERC20DividendCheckpointFactory contract was not deployed" ); - // STEP 5: Register the Modules with the ModuleRegistry contract + // STEP 8: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the ERC20DividendCheckpointFactory - await I_ModuleRegistry.registerModule(I_ERC20DividendCheckpointFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_ERC20DividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); // (C) : Register the Paid ERC20DividendCheckpointFactory - await I_ModuleRegistry.registerModule(P_ERC20DividendCheckpointFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(P_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(P_ERC20DividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_ERC20DividendCheckpointFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 9: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); @@ -175,41 +185,28 @@ contract('ERC20DividendCheckpoint', accounts => { "STFactory contract was not deployed", ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 10: Deploy the SecurityTokenRegistry contract - // Deploy the SecurityTokenregistry - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); - // Step 10: update the registries addresses from the PolymathRegistry contract + // Step 11: Deploy the proxy and attach the implementation contract to it. I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + // Step 12: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -218,6 +215,7 @@ contract('ERC20DividendCheckpoint', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -248,7 +246,7 @@ contract('ERC20DividendCheckpoint', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); assert.equal( diff --git a/test/f_ether_dividends.js b/test/f_ether_dividends.js index 4d58e26c8..00a8852a2 100644 --- a/test/f_ether_dividends.js +++ b/test/f_ether_dividends.js @@ -5,6 +5,7 @@ import { encodeProxyCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -52,6 +53,7 @@ contract('EtherDividendCheckpoint', accounts => { let I_EtherDividendCheckpoint; let I_GeneralTransferManager; let I_ExchangeTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; @@ -59,6 +61,7 @@ contract('EtherDividendCheckpoint', accounts => { let I_STFactory; let I_SecurityToken; let I_PolyToken; + let I_MRProxied; let I_PolymathRegistry; // SecurityToken Details @@ -76,6 +79,8 @@ contract('EtherDividendCheckpoint', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { // Accounts setup @@ -90,7 +95,7 @@ contract('EtherDividendCheckpoint', accounts => { account_investor4 = accounts[9]; account_temp = accounts[2]; - // ----------- POLYMATH NETWORK Configuration ------------ + // ----------- POLYMATH NETWORK Configuration ------------ // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); @@ -98,20 +103,25 @@ contract('EtherDividendCheckpoint', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -121,7 +131,7 @@ contract('EtherDividendCheckpoint', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -150,65 +160,53 @@ contract('EtherDividendCheckpoint', accounts => { // STEP 5: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the EtherDividendCheckpointFactory - await I_ModuleRegistry.registerModule(I_EtherDividendCheckpointFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_EtherDividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); // (C) : Register the Paid EtherDividendCheckpointFactory - await I_ModuleRegistry.registerModule(P_EtherDividendCheckpointFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(P_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); - - // Step 7: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_MRProxied.registerModule(P_EtherDividendCheckpointFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_EtherDividendCheckpointFactory.address, true, { from: account_polymath }); + + // Step 6: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 7: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -217,6 +215,7 @@ contract('EtherDividendCheckpoint', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -247,7 +246,7 @@ contract('EtherDividendCheckpoint', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index 8b22cf240..118dca77f 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -3,12 +3,13 @@ import {signData} from './helpers/signData'; import { pk } from './helpers/testprivateKey'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); const DummySTO = artifacts.require('./DummySTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -51,12 +52,14 @@ contract('GeneralPermissionManager', accounts => { let I_GeneralTransferManagerFactory; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_DummySTOFactory; let I_STFactory; let I_SecurityToken; + let I_MRProxied; let I_STRProxied; let I_DummySTO; let I_PolyToken; @@ -83,25 +86,11 @@ contract('GeneralPermissionManager', accounts => { const endTime = startTime + duration.days(80); // Add 80 days more const cap = web3.utils.toWei('10', 'ether'); const someString = "A string which is not used"; + const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; - let bytesSTO = web3.eth.abi.encodeFunctionCall({ - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'string', - name: '_someString' - } - ] - }, [startTime, endTime, cap, someString]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, someString]); before(async() => { // Accounts setup @@ -118,26 +107,31 @@ contract('GeneralPermissionManager', accounts => { // ----------- POLYMATH NETWORK Configuration ------------ - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -147,7 +141,7 @@ contract('GeneralPermissionManager', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -157,7 +151,7 @@ contract('GeneralPermissionManager', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 6: Deploy the GeneralDelegateManagerFactory P_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); @@ -167,7 +161,7 @@ contract('GeneralPermissionManager', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 4: Deploy the DummySTOFactory + // STEP 7: Deploy the DummySTOFactory I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -177,70 +171,57 @@ contract('GeneralPermissionManager', accounts => { "DummySTOFactory contract was not deployed" ); - // STEP 5: Register the Modules with the ModuleRegistry contract + // STEP 8: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (B) : Register the Paid GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(P_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(P_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(P_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + // Step 8: Deploy the STFactory contract - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - // Step 9: Deploy the SecurityTokenRegistry + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + // Step 9: Deploy the SecurityTokenRegistry contract - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -248,6 +229,7 @@ contract('GeneralPermissionManager', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -279,7 +261,7 @@ contract('GeneralPermissionManager', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index da4b0ee44..cda17f0cb 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -3,12 +3,13 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from './hel import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; import {signData} from './helpers/signData'; import { pk } from './helpers/testprivateKey'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); const DummySTO = artifacts.require('./DummySTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -52,6 +53,7 @@ contract('GeneralTransferManager', accounts => { let I_SecurityTokenRegistryProxy; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; @@ -59,6 +61,7 @@ contract('GeneralTransferManager', accounts => { let I_STFactory; let I_SecurityToken; let I_STRProxied; + let I_MRProxied; let I_DummySTO; let I_PolyToken; let I_PolymathRegistry; @@ -83,24 +86,9 @@ contract('GeneralTransferManager', accounts => { const endTime = startTime + duration.days(80); // Add 80 days more const cap = web3.utils.toWei('10', 'ether'); const someString = "A string which is not used"; - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'string', - name: '_someString' - } - ] - }; + const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { // Accounts setup @@ -118,7 +106,7 @@ contract('GeneralTransferManager', accounts => { account_affiliates1 = accounts[3]; account_affiliates2 = accounts[4]; - // ----------- POLYMATH NETWORK Configuration ------------ + // ----------- POLYMATH NETWORK Configuration ------------ // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); @@ -126,18 +114,24 @@ contract('GeneralTransferManager', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); // STEP 2: Deploy the GeneralTransferManagerFactory @@ -172,61 +166,49 @@ contract('GeneralTransferManager', accounts => { // STEP 5: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - - // Step 7: Deploy the STFactory contract - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - // Step 9: Deploy the SecurityTokenRegistry - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + + // Step 8: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + + // Step 9: Deploy the SecurityTokenRegistry contract + + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -234,6 +216,7 @@ contract('GeneralTransferManager', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -265,7 +248,7 @@ contract('GeneralTransferManager', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); @@ -304,7 +287,7 @@ contract('GeneralTransferManager', accounts => { }); it("Should successfully attach the STO factory with the security token", async () => { - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [latestTime() + duration.seconds(1000), latestTime() + duration.days(40), cap, someString]); + 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( diff --git a/test/helpers/encodeCall.js b/test/helpers/encodeCall.js index d3dac7f78..6a48f12a1 100644 --- a/test/helpers/encodeCall.js +++ b/test/helpers/encodeCall.js @@ -1,8 +1,14 @@ const abi = require('ethereumjs-abi') -export function encodeProxyCall(values) { - const parameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; - const methodId = abi.methodID("initialize", parameters).toString('hex'); - const params = abi.rawEncode(parameters, values).toString('hex'); +export function encodeProxyCall(parametersType, values) { + const methodId = abi.methodID("initialize", parametersType).toString('hex'); + const params = abi.rawEncode(parametersType, values).toString('hex'); return '0x' + methodId + params; } + + +export function encodeModuleCall(parametersType, values) { + const methodId = abi.methodID("configure", parametersType).toString('hex'); + const params = abi.rawEncode(parametersType, values).toString('hex'); + return '0x' + methodId + params; +} \ No newline at end of file diff --git a/test/i_Issuance.js b/test/i_Issuance.js index f6f4cdeb7..d2691674e 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -1,12 +1,13 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); const CappedSTO = artifacts.require('./CappedSTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -50,10 +51,12 @@ contract('Issuance', accounts => { let I_GeneralTransferManagerFactory; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_CappedSTOFactory; + let I_MRProxied; let I_STRProxied; let I_STFactory; let I_SecurityToken; @@ -79,35 +82,15 @@ contract('Issuance', accounts => { // Capped STO details //let startTime; // Start time will be 5000 seconds more than the latest time //let endTime; // Add 30 days more - const cap = new BigNumber(10000).times(new BigNumber(10).pow(18)); + const cap = web3.utils.toWei("10000"); const rate = 1000; const fundRaiseType = [0]; const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); const maxCost = cappedSTOSetupCost; - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes', - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + before(async() => { // Accounts setup @@ -127,20 +110,25 @@ contract('Issuance', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - - // STEP 2: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + // Step 2: Deploy the FeatureRegistry - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -150,7 +138,7 @@ contract('Issuance', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 5: Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -160,7 +148,7 @@ contract('Issuance', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 4: Deploy the CappedSTOFactory + // STEP 6: Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -170,21 +158,21 @@ contract('Issuance', accounts => { "CappedSTOFactory contract was not deployed" ); - // STEP 5: Register the Modules with the ModuleRegistry contract + // STEP 7: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_CappedSTOFactory.address, { from: token_owner }); - await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: token_owner }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 8: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); @@ -194,8 +182,7 @@ contract('Issuance', accounts => { "STFactory contract was not deployed", ); - - // Step 9: Deploy the SecurityTokenRegistry + // Step 9: Deploy the SecurityTokenRegistry contract I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -205,30 +192,18 @@ contract('Issuance', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -237,6 +212,7 @@ contract('Issuance', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -271,7 +247,7 @@ contract('Issuance', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), transferManagerKey); @@ -301,10 +277,10 @@ contract('Issuance', accounts => { ); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [(latestTime() + duration.seconds(5000)), (latestTime() + duration.days(30)), cap, rate, fundRaiseType, account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [(latestTime() + duration.seconds(5000)), (latestTime() + duration.days(30)), cap, rate, fundRaiseType, account_fundsReceiver]); await I_PolyToken.getTokens(cappedSTOSetupCost, account_polymath); await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: account_polymath}); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 1a1062770..b9517b8c9 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -5,6 +5,7 @@ import { encodeProxyCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -55,9 +56,11 @@ contract('ManualApprovalTransferManager', accounts => { let I_ManualApprovalTransferManager; let I_CountTransferManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; + let I_MRProxied; let I_STRProxied; let I_STFactory; let I_SecurityToken; @@ -79,6 +82,10 @@ contract('ManualApprovalTransferManager', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -94,26 +101,31 @@ contract('ManualApprovalTransferManager', accounts => { // ----------- POLYMATH NETWORK Configuration ------------ - // Step 0: Deploy the PolymathRegistry - I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); - // Step 1: Deploy the token Faucet and Mint tokens for token_owner - I_PolyToken = await PolyTokenFaucet.new(); - await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -123,7 +135,7 @@ contract('ManualApprovalTransferManager', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactoryFactory + // STEP 5: Deploy the GeneralDelegateManagerFactoryFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -133,7 +145,7 @@ contract('ManualApprovalTransferManager', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 4: Deploy the ManualApprovalTransferManagerFactory + // STEP 6: Deploy the ManualApprovalTransferManagerFactory I_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); assert.notEqual( I_ManualApprovalTransferManagerFactory.address.valueOf(), @@ -141,7 +153,7 @@ contract('ManualApprovalTransferManager', accounts => { "ManualApprovalTransferManagerFactory contract was not deployed" ); - // STEP 4: Deploy the Paid ManualApprovalTransferManagerFactory + // STEP 7: Deploy the Paid ManualApprovalTransferManagerFactory P_ManualApprovalTransferManagerFactory = await ManualApprovalTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); assert.notEqual( P_ManualApprovalTransferManagerFactory.address.valueOf(), @@ -149,7 +161,7 @@ contract('ManualApprovalTransferManager', accounts => { "ManualApprovalTransferManagerFactory contract was not deployed" ); - // STEP 4a: Deploy the CountTransferManagerFactory + // STEP 8: Deploy the CountTransferManagerFactory I_CountTransferManagerFactory = await CountTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); assert.notEqual( I_CountTransferManagerFactory.address.valueOf(), @@ -157,31 +169,31 @@ contract('ManualApprovalTransferManager', accounts => { "CountTransferManagerFactory contract was not deployed" ); - // STEP 5: Register the Modules with the ModuleRegistry contract + // STEP 9: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the ManualApprovalTransferManagerFactory - await I_ModuleRegistry.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); // (C) : Register the ManualApprovalTransferManagerFactory - await I_ModuleRegistry.registerModule(P_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(P_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(P_ManualApprovalTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_ManualApprovalTransferManagerFactory.address, true, { from: account_polymath }); // (D) : Register the CountTransferManagerFactory - await I_ModuleRegistry.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CountTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_CountTransferManagerFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 10: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); assert.notEqual( I_STFactory.address.valueOf(), @@ -189,7 +201,7 @@ contract('ManualApprovalTransferManager', accounts => { "STFactory contract was not deployed", ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 11: Deploy the SecurityTokenRegistry contract I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -199,29 +211,18 @@ contract('ManualApprovalTransferManager', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry + // Step 12: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); + // Step 13: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -261,7 +262,7 @@ contract('ManualApprovalTransferManager', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 718ea0b6e..6843db491 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -1,13 +1,14 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; -import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); const CappedSTO = artifacts.require('./CappedSTO.sol'); const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -19,6 +20,7 @@ const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); const MockFactory = artifacts.require('./MockFactory.sol'); +const TestSTOFactory = artifacts.require('./TestSTOFactory.sol'); const Web3 = require('web3'); const BigNumber = require('bignumber.js'); @@ -51,23 +53,27 @@ contract('ModuleRegistry', accounts => { let I_SecurityTokenRegistryProxy; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_CappedSTOFactory1; let I_CappedSTOFactory2; let I_STFactory; + let I_MRProxied; let I_SecurityToken; let I_STRProxied; let I_CappedSTO; let I_PolyToken; let I_MockFactory; + let I_TestSTOFactory; let I_DummySTOFactory; let I_PolymathRegistry; + let I_SecurityToken2; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; - const symbol = "DET"; + const symbol = "det"; const tokenDetails = "This is equity type of issuance"; const decimals = 18; @@ -87,33 +93,12 @@ contract('ModuleRegistry', accounts => { // Capped STO details let startTime; let endTime; - const cap = new BigNumber(10000).times(new BigNumber(10).pow(18)); + const cap = web3.utils.toWei("10000"); const rate = 1000; const fundRaiseType = [0]; - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes', - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256','uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { // Accounts setup @@ -134,19 +119,31 @@ contract('ModuleRegistry', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); assert.notEqual( I_ModuleRegistry.address.valueOf(), "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" + "ModuleRegistry contract was not deployed", ); + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + let tx = await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 2: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -177,19 +174,11 @@ contract('ModuleRegistry', accounts => { // Step 10: update the registries addresses from the PolymathRegistry contract I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + assert.notEqual( I_FeatureRegistry.address.valueOf(), @@ -198,8 +187,11 @@ contract('ModuleRegistry', accounts => { ); // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -208,485 +200,461 @@ contract('ModuleRegistry', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} ----------------------------------------------------------------------------- `); }); - describe("Test case of the module registry", async() => { - - it("Should verify the ownership of the module registry", async () => { - let _owner = await I_ModuleRegistry.owner.call(); - assert.equal(_owner, account_polymath, "Unauthenticated user deployed the contract"); - }); - - it("Should successfully deployed the Module Fatories", async () => { - - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); - - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralPermissionManagerFactory contract was not deployed" - ); - - - I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); - - assert.notEqual( - I_CappedSTOFactory1.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_temp }); - - assert.notEqual( - I_DummySTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "DummySTOFactory contract was not deployed" - ); - - I_MockFactory = await MockFactory.new(I_PolyToken.address, 1000 * Math.pow(10, 18), 0, 0, { from: account_temp }); - - assert.notEqual( - I_MockFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "MockFactory contract was not deployed" - ); - }); - }); - - describe("Test cases of register module", async() => { - - it("Should fail to register module if registration is paused", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.pause({ from: account_polymath}); - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Registration is paused`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should succssfully register the module", async() => { - await I_ModuleRegistry.unpause({ from: account_polymath}); - let tx = await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - - assert.equal( - tx.logs[0].args._moduleFactory, - I_GeneralTransferManagerFactory.address, - "GeneralTransferManagerFactory is not registerd successfully" - ); - - assert.equal(tx.logs[0].args._owner, account_polymath); - - tx = await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - - assert.equal( - tx.logs[0].args._moduleFactory, - I_GeneralPermissionManagerFactory.address, - "GeneralPermissionManagerFactory is not registerd successfully" - ); - - assert.equal(tx.logs[0].args._owner, account_polymath); - - tx = await I_ModuleRegistry.registerModule(I_CappedSTOFactory1.address, { from: account_polymath }); - - assert.equal( - tx.logs[0].args._moduleFactory, - I_CappedSTOFactory1.address, - "CappedSTOFactory is not registerd successfully" - ); - - assert.equal(tx.logs[0].args._owner, account_polymath); - - }); - - it("Should fail in registering the same module again", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Already Registered Module factory`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should fail in registering the module-- type = 0", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.registerModule(I_MockFactory.address, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Module factory of 0 type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Test cases for verify module", async() => { - - it("Should fail in calling the verify module. Because msg.sender should be account_polymath", async () => { - let errorThrown = false; - try { - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_temp }); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - - it("Should successfully verify the module -- true", async() => { - let tx = await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); - assert.equal( - tx.logs[0].args._moduleFactory, - I_GeneralPermissionManagerFactory.address, - "Failed in verifying the module" - ); - assert.equal( - tx.logs[0].args._verified, - true, - "Failed in verifying the module" - ); - }); + describe("Test cases for the ModuleRegistry", async() => { - it("Should successfully verify the module -- false", async() => { - let tx = await I_ModuleRegistry.verifyModule(I_CappedSTOFactory1.address, false, { from: account_polymath }); - assert.equal( - tx.logs[0].args._moduleFactory, - I_CappedSTOFactory1.address, - "Failed in verifying the module" - ); - assert.equal( - tx.logs[0].args._verified, - false, - "Failed in verifying the module" - ); - }); - - it("Should fail in verifying the module. Because the module is not registered", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Module is not registered`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Deploy the security token registry contract", async() => { - - it("Should successfully deploy the STR", async() => { - let tx = await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); - assert.equal( - tx.logs[0].args._moduleFactory, - I_GeneralTransferManagerFactory.address, - "Failed in verifying the module" - ); - assert.equal( - tx.logs[0].args._verified, - true, - "Failed in verifying the module" - ); - - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); - - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); - }); + describe("Test case for the upgradeFromregistry", async() => { - }); + it("Should successfully update the registry contract address -- failed because of bad owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.updateFromRegistry({from: account_temp}); + } catch(error) { + console.log(` tx -> revert because of bad owner`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); - describe("Test cases for the tag functions", async() => { - - it("Should fail in adding the tag. Because msg.sender is not the owner", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.addTagByModuleType(3,["Non-Refundable","Capped","ETH","POLY"],{from: account_temp}); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); + it("Should successfully update the registry contract addresses", async() => { + await I_MRProxied.updateFromRegistry({from: account_polymath}); + assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("securityTokenRegistry")), I_SecurityTokenRegistryProxy.address); + assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("featureRegistry")), I_FeatureRegistry.address); + assert.equal(await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")), I_PolyToken.address); + }); - it("Should successfully add the tag", async() => { - await I_ModuleRegistry.addTagByModuleType(3,["Non-Refundable","Capped","ETH","POLY"],{from: account_polymath}); - let tags = await I_ModuleRegistry.getTagByModuleType.call(3); - assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Non-Refundable"); }); - it("Should fail in removing the tag from the list", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.removeTagByModuleType(3,["Capped", "ETH"], {from: account_investor1}); - } catch(error) { - console.log(` tx revert -> msg.sender should be account_polymath`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); + describe("Test the state variables", async() => { - it("Should remove the tag from the list", async() => { - await I_ModuleRegistry.removeTagByModuleType(3,["Capped", "ETH"], {from:account_polymath}); - let tags = await I_ModuleRegistry.getTagByModuleType.call(3); - assert.equal(web3.utils.toAscii(tags[1]).replace(/\u0000/g, ''),""); - }); + it("Should be the right owner", async() => { + let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3('owner')); + assert.equal(_owner, account_polymath, "Owner should be the correct"); + }) - }); + it("Should be the expected value of the paused and intialised variable", async() => { + let _paused = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); + assert.isFalse(_paused, "Should be the false"); - describe("Generate the SecurityToken", async() => { + let _intialised = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("initialised")); + assert.isTrue(_intialised, "Values should be the true"); + }) - it("Should register the ticker before the generation of the security token", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let tx = await I_STRProxied.registerTicker(token_owner, symbol, name, { from : token_owner }); - assert.equal(tx.logs[0].args._owner, token_owner); - assert.equal(tx.logs[0].args._ticker, symbol); + it("Should be the expected value of the polymath registry", async() => { + let _polymathRegistry = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry")); + assert.equal(_polymathRegistry, I_PolymathRegistry.address, "Should be the right value of the address of the polymath registry"); + }); }); - it("Should generate the new security token with the same symbol as registered above", async () => { - await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); - let _blockNo = latestBlock(); - let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner, gas:85000000 }); - - // Verify the successful generation of the security token - assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); + describe("Test cases for the registering the module", async() => { - I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + it("Should fail to register the module -- when registerModule is paused", async() => { + await I_MRProxied.pause({from: account_polymath}); + let errorThrown = false; + try { + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert because already registered modules are not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await I_MRProxied.unpause({from: account_polymath}); + }) - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + it("Should register the module with the Module Registry", async() => { + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); + assert.equal(tx.logs[0].args._moduleFactory, I_GeneralTransferManagerFactory.address, "Should be the same address"); + assert.equal(tx.logs[0].args._owner, account_polymath, "Should be the right owner"); - // Verify that GeneralTransferManager module get added successfully or not - assert.equal(log.args._type.toNumber(), transferManagerKey); - assert.equal( - web3.utils.toAscii(log.args._name) - .replace(/\u0000/g, ''), - "GeneralTransferManager" - ); - }); + let _list = await I_MRProxied.getModuleListOfType(transferManagerKey); + assert.equal(_list.length, 1, "Length should be 1"); + assert.equal(_list[0], I_GeneralTransferManagerFactory.address); - it("Should intialize the auto attached modules", async () => { - let moduleData = await I_SecurityToken.modules(transferManagerKey, 0); - I_GeneralTransferManager = GeneralTransferManager.at(moduleData); - }); + let _reputation = await I_MRProxied.getReputationOfFactory(I_GeneralTransferManagerFactory.address); + assert.equal(_reputation.length, 0); + }); - }); + it("Should fail the register the module -- Already registered module", async() => { + let errorThrown = false; + try { + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert because already registered modules are not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }) - describe("test cases for Custom Modules", async() => { - - it("Should fail in adding module. Because module is un-verified", async() => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - let errorThrown = false; - try { - const tx = await I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner, gas: 60000000 }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); + it("Should fail in registering the module-- type = 0", async() => { + I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + let errorThrown = false; + try { + await I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); + } catch(error) { + console.log(` tx revert -> Module factory of 0 type`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); }); - it("Should fail to add module because custom modules not allowed", async() => { - I_CappedSTOFactory2 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); - - assert.notEqual( - I_CappedSTOFactory2.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "CappedSTOFactory contract was not deployed" - ); - - let tx = await I_ModuleRegistry.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); - - assert.equal( - tx.logs[0].args._moduleFactory, - I_CappedSTOFactory2.address, - "CappedSTOFactory is not registerd successfully" - ); - - assert.equal(tx.logs[0].args._owner, token_owner); - - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - - let errorThrown = false; - try { - tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner, gas: 60000000 }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); - }); + describe("Test case for verifyModule", async() => { - it("Should switch customModulesAllowed to true", async() => { - assert.equal(false, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be dissabled by default."); - let tx = await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", true, { from: account_polymath }); - assert.equal(true, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be switched to true."); - }); + it("Should fail in calling the verify module. Because msg.sender should be account_polymath", async () => { + let errorThrown = false; + try { + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_temp }); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); - it("Should successfully add module because custom modules switched on", async() => { - startTime = latestTime() + duration.seconds(5000); - endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + it("Should successfully verify the module -- true", async() => { + let tx = await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + assert.equal( + tx.logs[0].args._moduleFactory, + I_GeneralTransferManagerFactory.address, + "Failed in verifying the module" + ); + assert.equal( + tx.logs[0].args._verified, + true, + "Failed in verifying the module" + ); + }); - let tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner, gas: 60000000 }); + it("Should successfully verify the module -- false", async() => { + I_CappedSTOFactory1 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + await I_MRProxied.registerModule(I_CappedSTOFactory1.address, {from: account_polymath}); + let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory1.address, false, { from: account_polymath }); + assert.equal( + tx.logs[0].args._moduleFactory, + I_CappedSTOFactory1.address, + "Failed in verifying the module" + ); + assert.equal( + tx.logs[0].args._verified, + false, + "Failed in verifying the module" + ); + }); - assert.equal(tx.logs[2].args._type, stoKey, "CappedSTO doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name) - .replace(/\u0000/g, ''), - "CappedSTO", - "CappedSTOFactory module was not added" - ); - }); + it("Should fail in verifying the module. Because the module is not registered", async() => { + let errorThrown = false; + try { + await I_MRProxied.verifyModule(I_MockFactory.address, true, { from: account_polymath }); + } catch(error) { + console.log(` tx revert -> Module is not registered`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }) + + describe("Test cases for the useModule function of the module registry", async() => { + + it("Deploy the securityToken", async() => { + await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); + await I_STRProxied.registerTicker(account_issuer, symbol, name, {from: account_issuer}); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, true, {from: account_issuer}); + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase()); + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + }); - it("Should successfully add verified module", async() => { - 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"); - }); + it("Should fail in adding module. Because module is un-verified", async() => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let errorThrown = false; + try { + const tx = await I_SecurityToken.addModule(I_CappedSTOFactory1.address, bytesSTO, 0, 0, { from: token_owner, gas: 60000000 }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail to add module because custom modules not allowed", async() => { + I_CappedSTOFactory2 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: token_owner }); + + assert.notEqual( + I_CappedSTOFactory2.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "CappedSTOFactory contract was not deployed" + ); + + let tx = await I_MRProxied.registerModule(I_CappedSTOFactory2.address, { from: token_owner }); + + assert.equal( + tx.logs[0].args._moduleFactory, + I_CappedSTOFactory2.address, + "CappedSTOFactory is not registerd successfully" + ); + + assert.equal(tx.logs[0].args._owner, token_owner); + + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + + let errorThrown = false; + try { + tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner, gas: 60000000 }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should switch customModulesAllowed to true", async() => { + assert.equal(false, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be dissabled by default."); + let tx = await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", true, { from: account_polymath }); + assert.equal(true, await I_FeatureRegistry.getFeatureStatus.call("customModulesAllowed"), "Custom modules should be switched to true."); + }); + + it("Should successfully add module because custom modules switched on", async() => { + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + + let tx = await I_SecurityToken.addModule(I_CappedSTOFactory2.address, bytesSTO, 0, 0, { from: token_owner, gas: 60000000 }); + + assert.equal(tx.logs[2].args._type, stoKey, "CappedSTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name) + .replace(/\u0000/g, ''), + "CappedSTO", + "CappedSTOFactory module was not added" + ); + let _reputation = await I_MRProxied.getReputationOfFactory.call(I_CappedSTOFactory2.address); + assert.equal(_reputation.length, 1); + }); + + it("Should successfully add verified module", async() => { + I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, {from: account_polymath}); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, {from: account_polymath}); + let tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._type, permissionManagerKey, "module doesn't get deployed"); + }); - }); + it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --lower", async() => { + I_TestSTOFactory = await TestSTOFactory.new(I_PolyToken.address, 0, 0, 0, {from: account_polymath}); + await I_MRProxied.registerModule(I_TestSTOFactory.address, {from: token_owner}); + await I_MRProxied.verifyModule(I_TestSTOFactory.address, true, {from: account_polymath}); + // Taking the snapshot the revert the changes from here + let id = await takeSnapshot(); + await I_TestSTOFactory.changeSTVersionBounds("lowerBound", [0,1,0], {from: account_polymath}); + let _lstVersion = await I_TestSTOFactory.getLowerSTVersionBounds.call() + assert.equal(_lstVersion[2],0); + assert.equal(_lstVersion[1],1); + let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); + let errorThrown = false; + try { + let tx = await I_SecurityToken.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Incompatible with the lower bound of the Module factory`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + await revertToSnapshot(id); + }) + + it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --upper", async() => { + await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0,0,1], {from: account_polymath}); + let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() + assert.equal(_ustVersion[0],0); + assert.equal(_ustVersion[2],1); + await I_STRProxied.setProtocolVersion(I_STFactory.address, 1, 0, 1); + + // Generate the new securityToken + let newSymbol = "toro"; + await I_PolyToken.getTokens(web3.utils.toWei("500"), account_issuer); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), {from: account_issuer}); + await I_STRProxied.registerTicker(account_issuer, newSymbol, name, {from: account_issuer}); + let tx = await I_STRProxied.generateSecurityToken(name, newSymbol, tokenDetails, true, {from: account_issuer}); + assert.equal(tx.logs[1].args._ticker, newSymbol.toUpperCase()); + I_SecurityToken2 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + + let bytesData = encodeModuleCall(['uint256', 'uint256', 'uint256', 'string'],[latestTime(), (latestTime() + duration.days(1)), cap, "Test STO"]); + let errorThrown = false; + try { + let tx = await I_SecurityToken2.addModule(I_TestSTOFactory.address, bytesData, 0, 0, { from: token_owner }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Incompatible with the upper bound of the Module factory`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); - describe("Test cases for removeModule()", async() => { - - it("Should fail if msg.sender not curator or owner", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.removeModule(I_CappedSTOFactory2.address, { from: account_temp }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); }); - it("Should successfully remove module and delete data if msg.sender is curator", async() => { - let snap = await takeSnapshot(); - - let sto1 = await I_ModuleRegistry.moduleList.call(3,0); - let sto2 = await I_ModuleRegistry.moduleList.call(3,1); - - assert.equal(sto1,I_CappedSTOFactory1.address); - assert.equal(sto2,I_CappedSTOFactory2.address); - assert.equal((await I_ModuleRegistry.getModuleListOfType.call(3)).length, 2); - - let tx = await I_ModuleRegistry.removeModule(sto1, { from: account_polymath }); + describe("Test cases for the tag functions", async() => { - assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); - assert.equal(tx.logs[0].args._decisionMaker, account_polymath, "Event is not properly emitted for _decisionMaker"); + it("Should fail in adding the tag. Because msg.sender is not the owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.addTagByModuleType(3,["Non-Refundable","Capped","ETH","POLY"],{from: account_temp}); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); - let sto2_end = await I_ModuleRegistry.moduleList.call(3,0); + it("Should successfully add the tag", async() => { + await I_MRProxied.addTagByModuleType(3,["Non-Refundable","Capped","ETH","POLY"],{from: account_polymath}); + let tags = await I_MRProxied.getTagByModuleType.call(3); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Non-Refundable"); + }); - // re-ordering - assert.equal(sto2_end,sto2); - // delete related data - assert.equal(await I_ModuleRegistry.registry.call(sto1), 0); - assert.equal(await I_ModuleRegistry.getReputationOfFactory.call(sto1), 0); - assert.equal((await I_ModuleRegistry.getModuleListOfType.call(3)).length, 1); - assert.equal(await I_ModuleRegistry.verified.call(sto1), false); + it("Should fail in removing the tag from the list", async() => { + let errorThrown = false; + try { + await I_MRProxied.removeTagByModuleType(3,["Capped", "ETH"], {from: account_investor1}); + } catch(error) { + console.log(` tx revert -> msg.sender should be account_polymath`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); - await revertToSnapshot(snap); + it("Should remove the tag from the list", async() => { + await I_MRProxied.removeTagByModuleType(3,["Capped", "ETH"], {from:account_polymath}); + let tags = await I_MRProxied.getTagByModuleType.call(3); + assert.equal(web3.utils.toAscii(tags[1]).replace(/\u0000/g, ''),"POLY"); + }); }); - it("Should successfully remove module and delete data if msg.sender is owner", async() => { - let sto1 = await I_ModuleRegistry.moduleList.call(3,0); - let sto2 = await I_ModuleRegistry.moduleList.call(3,1); - - assert.equal(sto1,I_CappedSTOFactory1.address); - assert.equal(sto2,I_CappedSTOFactory2.address); - assert.equal((await I_ModuleRegistry.getModuleListOfType.call(3)).length, 2); + describe("Test case for the getAvailableModulesOfType()", async() => { - let tx = await I_ModuleRegistry.removeModule(sto2, { from: token_owner }); + it("Should get the list of available modules when the customModulesAllowed", async() => { + let _list = await I_MRProxied.getAvailableModulesOfType.call(3, I_SecurityToken.address); + assert.equal(_list[0], I_CappedSTOFactory2.address); + assert.equal(_list[1], I_TestSTOFactory.address); + }) - assert.equal(tx.logs[0].args._moduleFactory, sto2, "Event is not properly emitted for _moduleFactory"); - assert.equal(tx.logs[0].args._decisionMaker, token_owner, "Event is not properly emitted for _decisionMaker"); + it("Should get the list of available modules when the customModulesAllowed is not allowed", async() => { + await I_FeatureRegistry.setFeatureStatus("customModulesAllowed", false, { from: account_polymath }); + let _list = await I_MRProxied.getAvailableModulesOfType.call(3, I_SecurityToken.address); + assert.equal(_list[0], I_TestSTOFactory.address); + }) + }) - let sto1_end = await I_ModuleRegistry.moduleList.call(3,0); - - // re-ordering - assert.equal(sto1_end,sto1); - // delete related data - assert.equal(await I_ModuleRegistry.registry.call(sto2), 0); - assert.equal(await I_ModuleRegistry.getReputationOfFactory.call(sto2), 0); - assert.equal((await I_ModuleRegistry.getModuleListOfType.call(3)).length, 1); - assert.equal(await I_ModuleRegistry.verified.call(sto2), false); - }); + describe("Test cases for removeModule()", async() => { - it("Should fail if module already removed", async() => { - let errorThrown = false; - try { - await I_ModuleRegistry.removeModule(I_CappedSTOFactory2.address, { from: account_polymath }); - } catch(error) { - errorThrown = true; - console.log(` tx revert -> Module is un-verified`.grey); - ensureException(error); - } - assert.ok(errorThrown, message); + it("Should fail if msg.sender not curator or owner", async() => { + let errorThrown = false; + try { + await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_temp }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should successfully remove module and delete data if msg.sender is curator", async() => { + let snap = await takeSnapshot(); + + let sto1 = (await I_MRProxied.getModuleListOfType.call(3))[0]; + let sto2 = (await I_MRProxied.getModuleListOfType.call(3))[1]; + + assert.equal(sto1,I_CappedSTOFactory1.address); + assert.equal(sto2,I_CappedSTOFactory2.address); + assert.equal((await I_MRProxied.getModuleListOfType.call(3)).length, 3); + + let tx = await I_MRProxied.removeModule(sto1, { from: account_polymath }); + + assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); + assert.equal(tx.logs[0].args._decisionMaker, account_polymath, "Event is not properly emitted for _decisionMaker"); + + let sto2_end = (await I_MRProxied.getModuleListOfType.call(3))[1]; + + // re-ordering + assert.equal(sto2_end,sto2); + // delete related data + assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto1)), 0); + assert.equal(await I_MRProxied.getReputationOfFactory.call(sto1), 0); + assert.equal((await I_MRProxied.getModuleListOfType.call(3)).length, 2); + assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto1)), false); + + await revertToSnapshot(snap); + }); + + it("Should successfully remove module and delete data if msg.sender is owner", async() => { + let sto1 = (await I_MRProxied.getModuleListOfType.call(3))[0]; + let sto2 = (await I_MRProxied.getModuleListOfType.call(3))[1]; + + assert.equal(sto1,I_CappedSTOFactory1.address); + assert.equal(sto2,I_CappedSTOFactory2.address); + assert.equal((await I_MRProxied.getModuleListOfType.call(3)).length, 3); + + let tx = await I_MRProxied.removeModule(sto2, { from: token_owner }); + + assert.equal(tx.logs[0].args._moduleFactory, sto2, "Event is not properly emitted for _moduleFactory"); + assert.equal(tx.logs[0].args._decisionMaker, token_owner, "Event is not properly emitted for _decisionMaker"); + + let sto1_end = (await I_MRProxied.getModuleListOfType.call(3))[0]; + + // re-ordering + assert.equal(sto1_end,sto1); + // delete related data + assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); + assert.equal(await I_MRProxied.getReputationOfFactory.call(sto2), 0); + assert.equal((await I_MRProxied.getModuleListOfType.call(3)).length, 2); + assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); + }); + + it("Should fail if module already removed", async() => { + let errorThrown = false; + try { + await I_MRProxied.removeModule(I_CappedSTOFactory2.address, { from: account_polymath }); + } catch(error) { + errorThrown = true; + console.log(` tx revert -> Module is un-verified`.grey); + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }); - }); - - describe("Test cases for IRegistry functionality", async() => { + describe("Test cases for IRegistry functionality", async() => { describe("Test cases for reclaiming funds", async() => { it("Should successfully reclaim POLY tokens", async() => { - I_PolyToken.transfer(I_ModuleRegistry.address, web3.utils.toWei("1"), { from: token_owner }); + await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); let bal1 = await I_PolyToken.balanceOf.call(account_polymath); - await I_ModuleRegistry.reclaimERC20(I_PolyToken.address); + await I_MRProxied.reclaimERC20(I_PolyToken.address); let bal2 = await I_PolyToken.balanceOf.call(account_polymath); assert.isAtLeast(bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), bal2.dividedBy(new BigNumber(10).pow(18)).toNumber()); }); @@ -698,7 +666,7 @@ contract('ModuleRegistry', accounts => { it("Should fail to pause if msg.sender is not owner", async() => { let errorThrown = false; try { - await I_ModuleRegistry.pause({ from: account_temp }); + await I_MRProxied.pause({ from: account_temp }); } catch(error) { console.log(` tx revert -> msg.sender should be account_polymath`.grey); errorThrown = true; @@ -708,15 +676,15 @@ contract('ModuleRegistry', accounts => { }); it("Should successfully pause the contract", async() => { - await I_ModuleRegistry.pause({ from: account_polymath }); - let status = await I_ModuleRegistry.paused.call(); + await I_MRProxied.pause({ from: account_polymath }); + let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); assert.isOk(status); }); it("Should fail to unpause if msg.sender is not owner", async() => { let errorThrown = false; try { - await I_ModuleRegistry.unpause({ from: account_temp }); + await I_MRProxied.unpause({ from: account_temp }); } catch(error) { console.log(` tx revert -> msg.sender should be account_polymath`.grey); errorThrown = true; @@ -726,13 +694,14 @@ contract('ModuleRegistry', accounts => { }); it("Should successfully unpause the contract", async() => { - await I_ModuleRegistry.unpause({ from: account_polymath }); - let status = await I_ModuleRegistry.paused.call(); + await I_MRProxied.unpause({ from: account_polymath }); + let status = await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("paused")); assert.isNotOk(status); }); }); }); + }); -}); +}); \ No newline at end of file diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index f9cc37892..23ec5b8d4 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -1,10 +1,11 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -50,10 +51,12 @@ contract('PercentageTransferManager', accounts => { let I_GeneralPermissionManager; let I_PercentageTransferManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_STRProxied; + let I_MRProxied; let I_STFactory; let I_SecurityToken; let I_PolyToken; @@ -87,6 +90,9 @@ contract('PercentageTransferManager', accounts => { ] }, [holderPercentage]); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -106,20 +112,25 @@ contract('PercentageTransferManager', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - - // STEP 2: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + // Step 2: Deploy the FeatureRegistry - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // STEP 4(a): Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -129,7 +140,7 @@ contract('PercentageTransferManager', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 4(b): Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -139,8 +150,7 @@ contract('PercentageTransferManager', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - - // STEP 4: Deploy the PercentageTransferManager + // STEP 4(c): Deploy the PercentageTransferManager I_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); assert.notEqual( I_PercentageTransferManagerFactory.address.valueOf(), @@ -148,7 +158,7 @@ contract('PercentageTransferManager', accounts => { "PercentageTransferManagerFactory contract was not deployed" ); - // STEP 4: Deploy the PercentageTransferManager + // STEP 4(d): Deploy the PercentageTransferManager P_PercentageTransferManagerFactory = await PercentageTransferManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500", "ether"), 0, 0, {from:account_polymath}); assert.notEqual( P_PercentageTransferManagerFactory.address.valueOf(), @@ -160,32 +170,32 @@ contract('PercentageTransferManager', accounts => { // STEP 5: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the PercentageTransferManagerFactory - await I_ModuleRegistry.registerModule(I_PercentageTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_PercentageTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_PercentageTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_PercentageTransferManagerFactory.address, true, { from: account_polymath }); // (C) : Register the Paid PercentageTransferManagerFactory - await I_ModuleRegistry.registerModule(P_PercentageTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(P_PercentageTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(P_PercentageTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(P_PercentageTransferManagerFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 6: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 7: Deploy the SecurityTokenRegistry contract I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -195,30 +205,18 @@ contract('PercentageTransferManager', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -227,6 +225,7 @@ contract('PercentageTransferManager', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -257,7 +256,7 @@ contract('PercentageTransferManager', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), 2); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index b1e003259..c14156f2d 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -1,12 +1,13 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -45,12 +46,14 @@ contract('PreSaleSTO', accounts => { let I_GeneralTransferManagerFactory; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_PreSaleSTOFactory; let I_STFactory; let I_SecurityToken; + let I_MRProxied; let I_STRProxied; let I_PreSaleSTO; let I_PolyToken; @@ -75,17 +78,10 @@ contract('PreSaleSTO', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); - - // PreSale STO details - let endTime; // Start time will be 5000 seconds more than the latest time - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_endTime' - }] - }; + let endTime; + const STOParameters = ['uint256']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { @@ -106,18 +102,23 @@ contract('PreSaleSTO', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); // STEP 2: Deploy the GeneralTransferManagerFactory @@ -152,18 +153,18 @@ contract('PreSaleSTO', accounts => { // STEP 5: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_PreSaleSTOFactory.address, { from: token_owner }); - await I_ModuleRegistry.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: token_owner }); + await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 8: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); @@ -173,39 +174,28 @@ contract('PreSaleSTO', accounts => { "STFactory contract was not deployed", ); - // Step 9: Deploy the SecurityTokenRegistry - - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + // Step 9: Deploy the SecurityTokenRegistry contract - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); - - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); assert.notEqual( - I_FeatureRegistry.address.valueOf(), + I_SecurityTokenRegistry.address.valueOf(), "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", + "SecurityTokenRegistry contract was not deployed", ); + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -214,6 +204,7 @@ contract('PreSaleSTO', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -245,7 +236,7 @@ contract('PreSaleSTO', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), transferManagerKey); @@ -262,7 +253,7 @@ contract('PreSaleSTO', accounts => { }); it("Should fail to launch the STO due to endTime is 0", async () => { - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [0]); + let bytesSTO = encodeModuleCall(STOParameters, [0]); let errorThrown = false; try { const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner, gas: 26000000 }); @@ -276,7 +267,7 @@ contract('PreSaleSTO', accounts => { it("Should successfully attach the STO factory with the security token", async () => { endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [endTime]); + let bytesSTO = encodeModuleCall(STOParameters, [endTime]); const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner, gas: 26000000 }); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index ceef4c9f3..a53378c8b 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -1,12 +1,13 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const DummySTOFactory = artifacts.require('./DummySTOFactory.sol'); const DummySTO = artifacts.require('./DummySTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); @@ -52,6 +53,7 @@ contract('SecurityTokenRegistry', accounts => { let I_GeneralTransferManagerFactory; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; @@ -68,6 +70,7 @@ contract('SecurityTokenRegistry', accounts => { let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; let I_STRProxied; + let I_MRProxied; // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -90,26 +93,13 @@ contract('SecurityTokenRegistry', accounts => { const initRegFee = web3.utils.toWei("250"); const newRegFee = web3.utils.toWei("300"); + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + const STOParameters = ['uint256', 'uint256', 'uint256', 'string']; + // Capped STO details - const cap = 10000 * Math.pow(10, 18); + const cap = web3.utils.toWei("10000"); const someString = "Hello string"; - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'string', - name: '_someString' - }] - }; before(async() => { // Accounts setup @@ -123,7 +113,7 @@ contract('SecurityTokenRegistry', accounts => { token_owner = account_issuer; dummy_token = accounts[3]; - // ----------- POLYMATH NETWORK Configuration ------------ + // ----------- POLYMATH NETWORK Configuration ------------ // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); @@ -131,18 +121,23 @@ contract('SecurityTokenRegistry', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); // STEP 2: Deploy the GeneralTransferManagerFactory @@ -168,12 +163,12 @@ contract('SecurityTokenRegistry', accounts => { // STEP 4: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // Step 6: Deploy the STversionProxy contract @@ -196,9 +191,9 @@ contract('SecurityTokenRegistry', accounts => { ); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_DummySTOFactory.address, { from: token_owner }); + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: token_owner }); - // // Step 9: Deploy the SecurityTokenRegistry + // Step 9: Deploy the SecurityTokenRegistry I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -208,11 +203,11 @@ contract('SecurityTokenRegistry', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // // Step 10: update the registries addresses from the PolymathRegistry contract + // Step 9 (a): Deploy the proxy I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); // Step 10: Deploy the FeatureRegistry @@ -229,9 +224,11 @@ contract('SecurityTokenRegistry', accounts => { ); //Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); console.log(` --------------------- Polymath Network Smart Contracts: --------------------- @@ -239,6 +236,7 @@ contract('SecurityTokenRegistry', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -258,7 +256,7 @@ contract('SecurityTokenRegistry', accounts => { assert.isTrue(intialised, "Should be true"); let expiry = await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit")); - assert.equal(expiry.toNumber(), 1296000, "Expiry limit should be equal to 15 days"); + assert.equal(expiry.toNumber(), 5184000, "Expiry limit should be equal to 60 days"); let polytoken = await I_STRProxied.getAddressValues.call(web3.utils.soliditySha3("polyToken")); assert.equal(polytoken, I_PolyToken.address, "Should be the polytoken address"); @@ -556,7 +554,7 @@ contract('SecurityTokenRegistry', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + 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}`); @@ -593,13 +591,11 @@ contract('SecurityTokenRegistry', accounts => { "0x0000000000000000000000000000000000000000", "STFactory002 contract was not deployed", ); - await I_STRProxied.setProtocolVersion(I_STFactory002.address, "0.2.0", { from: account_polymath }); - - assert.equal( - web3.utils.toAscii(await I_STRProxied.getBytes32Values.call(web3.utils.soliditySha3("protocolVersion"))) - .replace(/\u0000/g, ''), - "0.2.0" - ); + await I_STRProxied.setProtocolVersion(I_STFactory002.address, 0, 2, 0, { from: account_polymath }); + let _protocol = await I_STRProxied.getProtocolVersion.call(); + assert.equal(_protocol[0], 0); + assert.equal(_protocol[1], 2); + assert.equal(_protocol[2], 0); }); it("Should register the ticker before the generation of the security token", async () => { @@ -622,7 +618,7 @@ contract('SecurityTokenRegistry', accounts => { assert.equal(tokens[0], I_SecurityToken.address); assert.equal(tokens[1], I_SecurityToken002.address); - const log = await promisifyLogWatch(I_SecurityToken002.LogModuleAdded({from: _blockNo}), 1); + 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( diff --git a/test/o_security_token.js b/test/o_security_token.js index f94354bae..8e4223f7d 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -1,12 +1,13 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import takeSnapshot, { increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); const CappedSTO = artifacts.require('./CappedSTO.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -57,6 +58,7 @@ contract('SecurityToken', accounts => { let I_GeneralTransferManagerFactory; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; @@ -64,6 +66,7 @@ contract('SecurityToken', accounts => { let I_STFactory; let I_SecurityToken; let I_STRProxied; + let I_MRProxied; let I_CappedSTO; let I_PolyToken; let I_TokenBurner; @@ -92,35 +95,14 @@ contract('SecurityToken', accounts => { // Capped STO details let startTime; let endTime; - const cap = new BigNumber(10000).times(new BigNumber(10).pow(18)); + const cap = web3.utils.toWei("10000"); const rate = 1000; const fundRaiseType = [0]; const cappedSTOSetupCost= web3.utils.toWei("20000","ether"); const maxCost = cappedSTOSetupCost; - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes', - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; before(async() => { @@ -139,7 +121,7 @@ contract('SecurityToken', accounts => { token_owner = account_issuer; account_controller = account_temp; - // ----------- POLYMATH NETWORK Configuration ------------ + // ----------- POLYMATH NETWORK Configuration ------------ // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); @@ -147,20 +129,25 @@ contract('SecurityToken', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - address_zero, - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4 (a): Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -170,7 +157,7 @@ contract('SecurityToken', accounts => { "GeneralTransferManagerFactory contract was not deployed" ); - // STEP 3: Deploy the GeneralDelegateManagerFactory + // STEP 4 (b): Deploy the GeneralDelegateManagerFactory I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -180,7 +167,7 @@ contract('SecurityToken', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 4: Deploy the CappedSTOFactory + // STEP 4 (c): Deploy the CappedSTOFactory I_CappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, cappedSTOSetupCost, 0, 0, { from: token_owner }); @@ -193,30 +180,28 @@ contract('SecurityToken', accounts => { // STEP 5: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_CappedSTOFactory.address, { from: token_owner }); - await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: token_owner }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 6: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); - assert.notEqual( - I_STFactory.address.valueOf(), - address_zero, - "STFactory contract was not deployed", - ); - - // Step 8: Deploy the SecurityTokenRegistry + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 7: Deploy the SecurityTokenRegistry contract I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -226,30 +211,18 @@ contract('SecurityToken', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - address_zero, - "FeatureRegistry contract was not deployed", - ); + // Step 8: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + // Step 9: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -257,6 +230,7 @@ contract('SecurityToken', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -287,7 +261,7 @@ contract('SecurityToken', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), transferManagerKey); @@ -306,49 +280,6 @@ contract('SecurityToken', accounts => { }); - // it("Should successfully attach the General permission manager factory with the security token", async () => { - // snap_Id = await takeSnapshot(); - // const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x", 0, 0, { from: token_owner }); - // assert.equal(tx.logs[2].args._type.toNumber(), permissionManagerKey, "General Permission Manager doesn't get deployed"); - // assert.equal( - // web3.utils.toAscii(tx.logs[2].args._name) - // .replace(/\u0000/g, ''), - // "GeneralPermissionManager", - // "GeneralPermissionManagerFactory module was not added" - // ); - // I_GeneralPermissionManager = GeneralPermissionManager.at(tx.logs[2].args._module); - // }); - - // it("Should lock the module which is already added in the security token", async() => { - // let errorThrown = false; - // try { - // await I_SecurityToken.lockModule(permissionManagerKey, { from: account_temp}); - // } catch(error) { - // console.log(` tx revert -> lockModule only be called by the owner of the SecurityToken`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // }); - - // it("Should lock the module which is already added in the security token", async() => { - // let tx = await I_SecurityToken.lockModule(permissionManagerKey, { from: token_owner}); - // assert.equal(tx.logs[0].args._moduleType, permissionManagerKey); - // }); - - // it("Should lock the module which is already added in the security token", async() => { - // let errorThrown = false; - // try { - // await I_SecurityToken.lockModule(permissionManagerKey, { from: token_owner}); - // } catch(error) { - // console.log(` tx revert -> Can't lock a already locked module`.grey); - // errorThrown = true; - // ensureException(error); - // } - // assert.ok(errorThrown, message); - // await revertToSnapshot(snap_Id); - // }); - it("Should mint the tokens before attaching the STO -- fail only be called by the owner", async() => { let errorThrown = false; let fromTime = latestTime(); @@ -510,7 +441,7 @@ contract('SecurityToken', accounts => { it("Should fail to attach the STO factory because not enough poly in contract", async () => { startTime = latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); let errorThrown = false; try { let tx = await I_SecurityToken.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner, gas: 60000000 }); @@ -525,7 +456,7 @@ contract('SecurityToken', accounts => { it("Should fail to attach the STO factory because max cost too small", async () => { startTime = latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); let errorThrown = false; @@ -542,7 +473,7 @@ contract('SecurityToken', accounts => { it("Should successfully attach the STO factory with the security token", async () => { startTime = latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner}); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index a1b55699b..0f0fbd6e7 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -1,13 +1,15 @@ - import latestTime from './helpers/latestTime'; +import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); const MockOracle = artifacts.require('./MockOracle.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -48,9 +50,11 @@ contract('USDTieredSTO', accounts => { let I_GeneralPermissionManagerFactory; let I_SecurityTokenRegistryProxy; let I_GeneralTransferManagerFactory; + let I_USDTieredSTOProxyFactory; let I_GeneralPermissionManager; let I_GeneralTransferManager; let I_ModuleRegistry; + let I_ModuleRegistryProxy; let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_USDTieredSTOFactory; @@ -59,6 +63,7 @@ contract('USDTieredSTO', accounts => { let I_STFactory; let I_SecurityToken; let I_STRProxied; + let I_MRProxied; let I_USDTieredSTO_Array = []; let I_PolyToken; let I_DaiToken; @@ -82,6 +87,9 @@ contract('USDTieredSTO', accounts => { const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + // STO Configuration Arrays let _startTime = []; let _endTime = []; @@ -203,20 +211,27 @@ contract('USDTieredSTO', accounts => { // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - // Step 1: Deploy the token Faucet + // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) I_DaiToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); - // STEP 2: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:POLYMATH}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: POLYMATH}); + // Step 2: Deploy the FeatureRegistry - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: POLYMATH + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); // STEP 3: Deploy the GeneralTransferManagerFactory @@ -238,9 +253,12 @@ contract('USDTieredSTO', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 5: Deploy the USDTieredSTOFactory + // STEP 5: Deploy the proxy + I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); + + // STEP 6: Deploy the USDTieredSTOFactory - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: ISSUER }); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), @@ -248,65 +266,52 @@ contract('USDTieredSTO', accounts => { "USDTieredSTOFactory contract was not deployed" ); - // STEP 6: Register the Modules with the ModuleRegistry contract + // STEP 7: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_USDTieredSTOFactory.address, { from: ISSUER }); - await I_ModuleRegistry.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: ISSUER }); + await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); - // Step 8: Deploy the STFactory contract + // Step 8: Deploy the STFactory contract - I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); - assert.notEqual( - I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "STFactory contract was not deployed", - ); + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 9: Deploy the SecurityTokenRegistry contract - I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistry.address, {from: POLYMATH}); + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: POLYMATH }); - assert.notEqual( - I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "SecurityTokenRegistry contract was not deployed", - ); + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); - // Step 10: update the registries addresses from the PolymathRegistry contract + // Step 10: Deploy the proxy and attach the implementation contract to it. I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: POLYMATH - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); - await I_ModuleRegistry.updateFromRegistry({from: POLYMATH}); + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); + await I_MRProxied.updateFromRegistry({from: POLYMATH}); // Step 12: Deploy & Register Mock Oracles I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY @@ -330,6 +335,7 @@ contract('USDTieredSTO', accounts => { USDOracle: ${I_USDOracle.address} POLYOracle: ${I_POLYOracle.address} USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} ----------------------------------------------------------------------------- `); }); @@ -353,7 +359,7 @@ contract('USDTieredSTO', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), TMKEY); diff --git a/test/q_usd_tiered_sto_sim.js b/test/q_usd_tiered_sto_sim.js index c12737967..f8ce2c1ea 100644 --- a/test/q_usd_tiered_sto_sim.js +++ b/test/q_usd_tiered_sto_sim.js @@ -8,11 +8,13 @@ const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); const MockOracle = artifacts.require('./MockOracle.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); const FeatureRegistry = artifacts.require('./FeatureRegistry.sol'); const STFactory = artifacts.require('./STFactory.sol'); +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory'); const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); @@ -45,9 +47,11 @@ contract('USDTieredSTO Sim', accounts => { // Contract Instance Declaration let I_GeneralPermissionManagerFactory; let I_GeneralTransferManagerFactory; + let I_USDTieredSTOProxyFactory; let I_SecurityTokenRegistryProxy; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_SecurityTokenRegistry; @@ -55,6 +59,7 @@ contract('USDTieredSTO Sim', accounts => { let I_USDOracle; let I_POLYOracle; let I_STFactory; + let I_MRProxied; let I_STRProxied; let I_SecurityToken; let I_USDTieredSTO_Array = []; @@ -80,6 +85,9 @@ contract('USDTieredSTO Sim', accounts => { const USDETH = BigNumber(500).mul(10**18); // 500 USD/ETH const USDPOLY = BigNumber(25).mul(10**16); // 0.25 USD/POLY + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + // STO Configuration Arrays let _startTime = []; let _endTime = []; @@ -168,25 +176,33 @@ contract('USDTieredSTO Sim', accounts => { NOTAPPROVED = accounts[8]; INVESTOR1 = accounts[9]; - // ----------- POLYMATH NETWORK Configuration ------------ + // ----------- POLYMATH NETWORK Configuration ------------ // Step 0: Deploy the PolymathRegistry I_PolymathRegistry = await PolymathRegistry.new({from: POLYMATH}); - // Step 1: Deploy the token Faucet + // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) I_DaiToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), ISSUER); - // STEP 2: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:POLYMATH}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: POLYMATH}); + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: POLYMATH + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); // STEP 3: Deploy the GeneralTransferManagerFactory @@ -208,29 +224,33 @@ contract('USDTieredSTO Sim', accounts => { "GeneralDelegateManagerFactory contract was not deployed" ); - // STEP 5: Deploy the USDTieredSTOFactory + // STEP 5: Deploy the proxy + I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new({ from: POLYMATH }); - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: ISSUER }); + // STEP 6: Deploy the USDTieredSTOFactory + + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: ISSUER }); + + assert.notEqual( + I_USDTieredSTOFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "USDTieredSTOFactory contract was not deployed" + ); + - assert.notEqual( - I_USDTieredSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "USDTieredSTOFactory contract was not deployed" - ); - - // STEP 6: Register the Modules with the ModuleRegistry contract + // STEP 7: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); // (C) : Register the STOFactory - await I_ModuleRegistry.registerModule(I_USDTieredSTOFactory.address, { from: ISSUER }); - await I_ModuleRegistry.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: ISSUER }); + await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); // Step 8: Deploy the STFactory contract @@ -254,29 +274,16 @@ contract('USDTieredSTO Sim', accounts => { // Step 10: update the registries addresses from the PolymathRegistry contract I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: POLYMATH - }); + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: POLYMATH}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: POLYMATH}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - - // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); - await I_ModuleRegistry.updateFromRegistry({from: POLYMATH}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: POLYMATH}); + await I_MRProxied.updateFromRegistry({from: POLYMATH}); // Step 12: Deploy & Register Mock Oracles I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY @@ -290,6 +297,7 @@ contract('USDTieredSTO Sim', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -300,6 +308,7 @@ contract('USDTieredSTO Sim', accounts => { USDOracle: ${I_USDOracle.address} POLYOracle: ${I_POLYOracle.address} USDTieredSTOFactory: ${I_USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${I_USDTieredSTOProxyFactory.address} ----------------------------------------------------------------------------- `); }); @@ -323,7 +332,7 @@ contract('USDTieredSTO Sim', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), TMKEY); diff --git a/test/r_concurrent_STO.js b/test/r_concurrent_STO.js index 477b9de40..91b7ab7d5 100644 --- a/test/r_concurrent_STO.js +++ b/test/r_concurrent_STO.js @@ -1,7 +1,7 @@ import latestTime from './helpers/latestTime'; import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; // Import contract ABIs const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); @@ -12,6 +12,7 @@ const PreSaleSTOFactory = artifacts.require('./PreSaleSTOFactory.sol'); const PreSaleSTO = artifacts.require('./PreSaleSTO.sol'); const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -42,9 +43,11 @@ contract('Concurrent STO', accounts => { let I_GeneralPermissionManager; let I_GeneralTransferManagerFactory; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_FeatureRegistry; let I_STFactory; + let I_MRProxied; let I_STRProxied; let I_SecurityTokenRegistry; let I_SecurityToken; @@ -70,57 +73,12 @@ contract('Concurrent STO', accounts => { // Configure function signature for STO deployment - const cappedFuncSig = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseTypes', - },{ - type: 'address', - name: '_fundsReceiver' - }] - }; - - const dummyFuncSig = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'string', - name: '_someString' - }] - } - - const presaleFuncSig = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_endTime' - }] - } - + const CappedSTOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + const DummySTOParameters = ['uint256', 'uint256', 'uint256', 'string']; + const PresaleSTOParameters = ['uint256']; + before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -137,12 +95,24 @@ contract('Concurrent STO', accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), account_issuer); - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); // STEP 2: Deploy the GeneralTransferManagerFactory @@ -179,24 +149,24 @@ contract('Concurrent STO', accounts => { // STEP 5: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: account_polymath }); // (C) : Register the STO Factories - await I_ModuleRegistry.registerModule(I_CappedSTOFactory.address, { from: account_issuer }); - await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: account_issuer }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: account_polymath }); - await I_ModuleRegistry.registerModule(I_DummySTOFactory.address, { from: account_issuer }); - await I_ModuleRegistry.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_issuer }); + await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); - await I_ModuleRegistry.registerModule(I_PreSaleSTOFactory.address, { from: account_issuer }); - await I_ModuleRegistry.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_PreSaleSTOFactory.address, { from: account_issuer }); + await I_MRProxied.verifyModule(I_PreSaleSTOFactory.address, true, { from: account_polymath }); - // Step 7: Deploy the STFactory contract + // Step 8: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); @@ -206,7 +176,7 @@ contract('Concurrent STO', accounts => { "STFactory contract was not deployed", ); - // Step 9: Deploy the SecurityTokenRegistry + // Step 9: Deploy the SecurityTokenRegistry contract I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); @@ -216,31 +186,18 @@ contract('Concurrent STO', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 10: update the registries addresses from the PolymathRegistry contract - I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); - await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); - I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); - - - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); + // Step 10: Deploy the proxy and attach the implementation contract to it. + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); + I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); // Step 11: update the registries addresses from the PolymathRegistry contract - await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -249,6 +206,7 @@ contract('Concurrent STO', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -285,7 +243,7 @@ contract('Concurrent STO', accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), transferManagerKey); @@ -325,14 +283,14 @@ contract('Concurrent STO', accounts => { const MAX_MODULES = 10; const startTime = latestTime() + duration.days(1); const endTime = latestTime() + duration.days(90); - const cap = new BigNumber(10000).times(new BigNumber(10).pow(18)); + const cap = web3.utils.toWei("10000"); const rate = 1000; const fundRaiseType = [0]; const budget = 0; const maxCost = STOSetupCost; - const cappedBytesSig = web3.eth.abi.encodeFunctionCall(cappedFuncSig, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); - const dummyBytesSig = web3.eth.abi.encodeFunctionCall(dummyFuncSig, [startTime, endTime, cap, 'Hello']); - const presaleBytesSig = web3.eth.abi.encodeFunctionCall(presaleFuncSig, [endTime]); + const cappedBytesSig = encodeModuleCall(CappedSTOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + const dummyBytesSig = encodeModuleCall(DummySTOParameters, [startTime, endTime, cap, 'Hello']); + const presaleBytesSig = encodeModuleCall(PresaleSTOParameters, [endTime]); for (var STOIndex = 0; STOIndex < MAX_MODULES; STOIndex++) { await I_PolyToken.getTokens(STOSetupCost, account_issuer); diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index 0a576e110..6c1fa9102 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -4,9 +4,10 @@ const BigNumber = require('bignumber.js'); import latestTime from './helpers/latestTime'; import { duration } from './helpers/utils'; -import { encodeProxyCall } from './helpers/encodeCall'; +import { encodeProxyCall, encodeModuleCall } from './helpers/encodeCall'; const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const USDTieredSTOFactory = artifacts.require('./USDTieredSTOFactory.sol'); const CappedSTOFactory = artifacts.require('./CappedSTOFactory.sol'); const USDTieredSTO = artifacts.require('./USDTieredSTO.sol'); @@ -14,6 +15,7 @@ const CappedSTO = artifacts.require('./CappedSTO.sol'); const PolyOracle = artifacts.require('./PolyOracle.sol'); const ETHOracle = artifacts.require('./MakerDAOOracle.sol'); const ModuleRegistry = artifacts.require('./ModuleRegistry.sol'); +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); const SecurityTokenRegistry = artifacts.require('./SecurityTokenRegistry.sol'); const SecurityTokenRegistryProxy = artifacts.require('./SecurityTokenRegistryProxy.sol'); @@ -64,11 +66,13 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { let I_PolyToken; let I_DaiToken; let I_ModuleRegistry; + let I_ModuleRegistryProxy; let I_GeneralTransferManagerFactory; let I_GeneralPermissionManagerFactory; let I_SecurityTokenRegistryProxy; let I_FeatureRegistry; let I_STFactory; + let I_MRProxied; let I_STRProxied; let I_STRProxiedNew; @@ -80,6 +84,7 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { //let I_SecurityToken3; let I_USDTieredSTOFactory; + let I_USDTieredSTOProxyFactory let I_USDOracle; let I_POLYOracle; let I_USDTieredSTO; @@ -89,6 +94,9 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { let I_CappedSTO; let I_ManualApprovalTransferManagerFactory; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + const STOParameters = ['uint256', 'uint256', 'uint256', 'uint256', 'uint8[]', 'address']; // Prepare polymath network status before(async() => { // Accounts setup @@ -121,15 +129,16 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { assert.equal(tx.logs[0].args._newAddress, I_PolyToken.address); // STEP 2: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:POLYMATH}); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); - tx = await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: POLYMATH}); + I_ModuleRegistry = await ModuleRegistry.new({from: POLYMATH}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: POLYMATH}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, POLYMATH]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: POLYMATH}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + tx = await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: POLYMATH}); assert.equal(tx.logs[0].args._nameKey, "ModuleRegistry"); - assert.equal(tx.logs[0].args._newAddress, I_ModuleRegistry.address); + assert.equal(tx.logs[0].args._newAddress, I_ModuleRegistryProxy.address); // STEP 3: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: POLYMATH }); @@ -157,16 +166,16 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { // STEP 6: Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: POLYMATH }); // (B) : Register the GeneralDelegateManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerFactory.address, true, { from: POLYMATH }); // (C) : Register the CappedSTOFactory - await I_ModuleRegistry.registerModule(I_CappedSTOFactory.address, { from: POLYMATH }); - await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, true, { from: POLYMATH }); + await I_MRProxied.registerModule(I_CappedSTOFactory.address, { from: POLYMATH }); + await I_MRProxied.verifyModule(I_CappedSTOFactory.address, true, { from: POLYMATH }); // Step 8: Deploy the STFactory contract I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : POLYMATH }); @@ -188,7 +197,7 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { // Step 10: update the registries addresses from the PolymathRegistry contract I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: POLYMATH}); - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, REGFEE, REGFEE, I_PolyToken.address, POLYMATH]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: POLYMATH}); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); @@ -209,7 +218,7 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { // Step 11: update the registries addresses from the PolymathRegistry contract await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_STRProxied.address, {from: POLYMATH}); - await I_ModuleRegistry.updateFromRegistry({from: POLYMATH}); + await I_MRProxied.updateFromRegistry({from: POLYMATH}); // Step 12: Mint tokens to ISSUERs await I_PolyToken.getTokens(REGFEE * 2, ISSUER1); @@ -254,6 +263,7 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { PolymathRegistry: ${PolymathRegistry.address} SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} ModuleRegistry: ${ModuleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} @@ -299,7 +309,8 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { describe("USDTieredSTOFactory deploy", async() => { // Step 1: Deploy USDTieredSTOFactory\ it("Should successfully deploy USDTieredSTOFactory", async() => { - I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); + I_USDTieredSTOProxyFactory = await USDTieredSTOProxyFactory.new(); + I_USDTieredSTOFactory = await USDTieredSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, I_USDTieredSTOProxyFactory.address, { from: POLYMATH }); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), "0x0000000000000000000000000000000000000000", @@ -310,9 +321,9 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { }); // Step 2: Register and verify it("Should successfully register and verify USDTieredSTOFactory contract", async() => { - let tx = await I_ModuleRegistry.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); + let tx = await I_MRProxied.registerModule(I_USDTieredSTOFactory.address, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); - tx = await I_ModuleRegistry.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); + tx = await I_MRProxied.verifyModule(I_USDTieredSTOFactory.address, true, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_USDTieredSTOFactory.address); assert.isTrue(tx.logs[0].args._verified); }); @@ -333,16 +344,16 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { // Step 2: Register and verify it("Should successfully register and verify new CappedSTOFactory contract", async() => { - let tx = await I_ModuleRegistry.registerModule(I_UpgradedCappedSTOFactory.address, { from: POLYMATH }); + let tx = await I_MRProxied.registerModule(I_UpgradedCappedSTOFactory.address, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); - tx = await I_ModuleRegistry.verifyModule(I_UpgradedCappedSTOFactory.address, true, { from: POLYMATH }); + tx = await I_MRProxied.verifyModule(I_UpgradedCappedSTOFactory.address, true, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_UpgradedCappedSTOFactory.address); assert.isTrue(tx.logs[0].args._verified); }); // Step 3: Unverify old CappedSTOFactory it("Should successfully unverify old CappedSTOFactory contract", async() => { - let tx = await I_ModuleRegistry.verifyModule(I_CappedSTOFactory.address, false, { from: POLYMATH }); + let tx = await I_MRProxied.verifyModule(I_CappedSTOFactory.address, false, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_CappedSTOFactory.address); assert.isFalse(tx.logs[0].args._verified); }); @@ -361,9 +372,9 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { // Step 2: Register and verify it("Should successfully register and verify new ManualApprovalTransferManagerFactory contract", async() => { - let tx = await I_ModuleRegistry.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: POLYMATH }); + let tx = await I_MRProxied.registerModule(I_ManualApprovalTransferManagerFactory.address, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); - tx = await I_ModuleRegistry.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: POLYMATH }); + tx = await I_MRProxied.verifyModule(I_ManualApprovalTransferManagerFactory.address, true, { from: POLYMATH }); assert.equal(tx.logs[0].args._moduleFactory, I_ManualApprovalTransferManagerFactory.address); assert.isTrue(tx.logs[0].args._verified); }); @@ -498,36 +509,12 @@ contract('Upgrade from v1.3.0 to v1.4.0', accounts => { it("Should successfully launch CappedSTO for third security token", async() => { let startTime = latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - let cap = BigNumber(500000).mul(10**18); + let cap = web3.utils.toWei("500000"); let rate = 1000; let fundRaiseType = 0; let fundsReceiver = ISSUER3; - const functionSignature = { - name: 'configure', - type: 'function', - inputs: [{ - type: 'uint256', - name: '_startTime' - },{ - type: 'uint256', - name: '_endTime' - },{ - type: 'uint256', - name: '_cap' - },{ - type: 'uint256', - name: '_rate' - },{ - type: 'uint8[]', - name: '_fundRaiseType', - },{ - type: 'address', - name: '_fundsReceiver' - } - ] - }; - let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, [startTime, endTime, cap, rate, [fundRaiseType], fundsReceiver]); + 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"); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 622f43d60..dc258f670 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -8,6 +8,7 @@ const SecurityTokenRegistryMock = artifacts.require("./SecurityTokenRegistryMock const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') const STFactory = artifacts.require('./STFactory.sol'); const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); const SecurityToken = artifacts.require('./SecurityToken.sol'); @@ -26,8 +27,10 @@ contract ("SecurityTokenRegistryProxy", accounts => { let I_SecurityTokenRegistryMock; let I_STFactory; let I_PolymathRegistry; + let I_ModuleRegistryProxy; let I_PolyToken; let I_STRProxied; + let I_MRProxied; let I_SecurityToken; let I_ModuleRegistry; let I_FeatureRegistry; @@ -49,7 +52,8 @@ contract ("SecurityTokenRegistryProxy", accounts => { const decimals = 18; const transferManagerKey = 2; - + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; async function readStorage(contractAddress, slot) { return await web3.eth.getStorageAt(contractAddress, slot); @@ -69,20 +73,25 @@ contract ("SecurityTokenRegistryProxy", accounts => { // Step 1: Deploy the token Faucet and Mint tokens for token_owner I_PolyToken = await PolyTokenFaucet.new(); await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); - await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}) - // STEP 2: Deploy the ModuleRegistry + // Step 2: Deploy the FeatureRegistry - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); - assert.notEqual( - I_ModuleRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "ModuleRegistry contract was not deployed" - ); + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); - // STEP 2: Deploy the GeneralTransferManagerFactory + // STEP 4: Deploy the GeneralTransferManagerFactory I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); @@ -95,8 +104,8 @@ contract ("SecurityTokenRegistryProxy", accounts => { // Register the Modules with the ModuleRegistry contract // (A) : Register the GeneralTransferManagerFactory - await I_ModuleRegistry.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); - await I_ModuleRegistry.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); // Step 3: Deploy the STFactory contract @@ -120,24 +129,12 @@ contract ("SecurityTokenRegistryProxy", accounts => { I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); - // Step 10: Deploy the FeatureRegistry - - I_FeatureRegistry = await FeatureRegistry.new( - I_PolymathRegistry.address, - { - from: account_polymath - }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - assert.notEqual( - I_FeatureRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "FeatureRegistry contract was not deployed", - ); - // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -160,7 +157,7 @@ contract ("SecurityTokenRegistryProxy", accounts => { // __upgradeabilityOwner -- index 13 it("Should attach the implementation and version", async() => { - let bytesProxy = encodeProxyCall([I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); + let bytesProxy = encodeProxyCall(STRProxyParameters, [I_PolymathRegistry.address, I_STFactory.address, initRegFee, initRegFee, I_PolyToken.address, account_polymath]); await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, {from: account_polymath}); let c = OwnedUpgradeabilityProxy.at(I_SecurityTokenRegistryProxy.address); assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address); @@ -169,7 +166,7 @@ contract ("SecurityTokenRegistryProxy", accounts => { }); it("Verify the initialize data", async() => { - assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 15*24*60*60, "Should equal to 60 days"); + assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("expiryLimit"))).toNumber(), 60*24*60*60, "Should equal to 60 days"); assert.equal((await I_STRProxied.getUintValues.call(web3.utils.soliditySha3("tickerRegFee"))).toNumber(), web3.utils.toWei("250")); }); @@ -196,7 +193,7 @@ contract ("SecurityTokenRegistryProxy", accounts => { I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - const log = await promisifyLogWatch(I_SecurityToken.LogModuleAdded({from: _blockNo}), 1); + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({from: _blockNo}), 1); // Verify that GeneralTransferManager module get added successfully or not assert.equal(log.args._type.toNumber(), transferManagerKey); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js new file mode 100644 index 000000000..82583d594 --- /dev/null +++ b/test/u_module_registry_proxy.js @@ -0,0 +1,347 @@ +import { duration, ensureException, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { encodeProxyCall } from './helpers/encodeCall'; + +const SecurityTokenRegistry = artifacts.require("./SecurityTokenRegistry.sol"); +const SecurityTokenRegistryProxy = artifacts.require("./SecurityTokenRegistryProxy.sol"); +const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); +const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); +const ModuleRegistryMock = artifacts.require("./ModuleRegistryMock.sol"); +const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); +const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') +const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') +const ModuleRegistryProxy = artifacts.require('./ModuleRegistryProxy.sol') +const STFactory = artifacts.require('./STFactory.sol'); +const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); +const SecurityToken = artifacts.require('./SecurityToken.sol'); +const FeatureRegistry = artifacts.require('./FeatureRegistry.sol') + +const Web3 = require('web3'); +const BigNumber = require('bignumber.js'); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) // Hardcoded development port + +contract ("ModuleRegistryProxy", accounts => { + + + let I_SecurityTokenRegistry; + let I_SecurityTokenRegistryProxy; + let I_GeneralTransferManagerFactory; + let I_GeneralPermissionManagerfactory; + let I_ModuleRegistryMock; + let I_STFactory; + let I_PolymathRegistry; + let I_ModuleRegistryProxy; + let I_PolyToken; + let I_STRProxied; + let I_MRProxied; + let I_SecurityToken; + let I_ModuleRegistry; + let I_FeatureRegistry; + + let account_polymath; + let account_temp; + let token_owner; + let account_polymath_new; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + const version = "1.0.0"; + const message = "Transaction Should Fail!"; + + // SecurityToken Details for funds raise Type ETH + const name = "Team"; + const symbol = "SAP"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + + const transferManagerKey = 2; + const STRProxyParameters = ['address', 'address', 'uint256', 'uint256', 'address', 'address']; + const MRProxyParameters = ['address', 'address']; + + async function readStorage(contractAddress, slot) { + return await web3.eth.getStorageAt(contractAddress, slot); + } + + before(async() => { + account_polymath = accounts[0]; + account_temp = accounts[1]; + token_owner = accounts[2]; + account_polymath_new = accounts[3]; + + // ----------- POLYMATH NETWORK Configuration ------------ + + // Step 0: Deploy the PolymathRegistry + I_PolymathRegistry = await PolymathRegistry.new({from: account_polymath}); + + // Step 1: Deploy the token Faucet and Mint tokens for token_owner + I_PolyToken = await PolyTokenFaucet.new(); + await I_PolyToken.getTokens((10000 * Math.pow(10, 18)), token_owner); + + // Step 2: Deploy the FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + // STEP 3: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + // Step 3 (b): Deploy the proxy and attach the implementation contract to it + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + let bytesMRProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesMRProxy, {from: account_polymath}); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + + // Step 4: Deploy the SecurityTokenRegistry + I_SecurityTokenRegistry = await SecurityTokenRegistry.new({from: account_polymath }); + + assert.notEqual( + I_SecurityTokenRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SecurityTokenRegistry contract was not deployed", + ); + + I_SecurityTokenRegistryProxy = await SecurityTokenRegistryProxy.new({from: account_polymath}); + + // Step 11: update the registries addresses from the PolymathRegistry contract + await I_PolymathRegistry.changeAddress("PolyToken", I_PolyToken.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + await I_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${PolymathRegistry.address} + SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${SecurityTokenRegistry.address} + ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} + STFactory: ${STFactory.address} + GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} + ----------------------------------------------------------------------------- + `); + }); + + describe("Attach the implementation address", async() => { + + // Storage + // __version -- index 11 + // __implementation -- index 12 + // __upgradeabilityOwner -- index 13 + + it("Should attach the MR implementation and version", async() => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [I_PolymathRegistry.address, account_polymath]); + await I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, {from: account_polymath}); + let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.0.0"); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + }); + + it("Deploy the essential smart contracts", async() => { + // STEP 4: Deploy the GeneralTransferManagerFactory + + I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralTransferManagerFactory contract was not deployed" + ); + + // Register the Modules with the ModuleRegistry contract + + // (A) : Register the GeneralTransferManagerFactory + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); + + + // Step 3: Deploy the STFactory contract + + I_STFactory = await STFactory.new(I_GeneralTransferManagerFactory.address, {from : account_polymath }); + + assert.notEqual( + I_STFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "STFactory contract was not deployed", + ); + }) + + it("Verify the initialize data", async() => { + assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner"))), account_polymath, "Should equal to right address"); + assert.equal((await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("polymathRegistry"))), I_PolymathRegistry.address); + }); + + }) + + describe("Feed some data in storage", async() => { + + it("Register and verify the new module", async() => { + + I_GeneralPermissionManagerfactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + + assert.notEqual( + I_GeneralPermissionManagerfactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "GeneralPermissionManagerFactory contract was not deployed" + ); + + await I_MRProxied.registerModule(I_GeneralPermissionManagerfactory.address, { from: account_polymath }); + await I_MRProxied.verifyModule(I_GeneralPermissionManagerfactory.address, true, { from: account_polymath }); + + }); + + it("Should add the tags successfuly", async() => { + await I_MRProxied.addTagByModuleType(3,["Non-Refundable","Capped","ETH","POLY"],{from: account_polymath}); + let tags = await I_MRProxied.getTagByModuleType.call(3); + assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ''),"Non-Refundable"); + }) + }) + + describe("Upgrade the imlplementation address", async() => { + + it("Should upgrade the version and implementation address -- fail bad owner", async() => { + let errorThrown = false; + I_ModuleRegistryMock = await ModuleRegistryMock.new({from: account_polymath}); + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistryMock.address, {from: account_temp}); + } catch(error) { + console.log(` tx -> revert bad owner of the proxy contract`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implementaion address should be a contract address", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", account_temp, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implementaion address should be a contract address`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implemenation address should not be 0x", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", "0x00000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implemenation address should not be 0x`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- Implemenation address should not be the same address", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistry.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert Implemenation address should not be the same address`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- same version as previous is not allowed", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("1.0.0", I_ModuleRegistryMock.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert same version as previous is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and implementation address -- empty version string is not allowed", async() => { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.upgradeTo("", I_ModuleRegistryMock.address, {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert empty version string is not allowed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should upgrade the version and the implementation address successfully", async() => { + await I_ModuleRegistryProxy.upgradeTo("1.1.0", I_ModuleRegistryMock.address, {from: account_polymath}); + let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.1.0", "Version mis-match"); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistryMock.address, "Implemnted address is not matched"); + I_MRProxied = await ModuleRegistryMock.at(I_ModuleRegistryProxy.address); + }); + }); + + describe("Execute functionality of the implementation contract on the earlier storage", async() => { + + it("Should get the previous data", async() => { + let _data = await I_MRProxied.getTagByModuleType.call(3); + assert.equal(web3.utils.toUtf8(_data[0]), "Non-Refundable"); + assert.equal(web3.utils.toUtf8(_data[1]), "Capped"); + assert.equal(web3.utils.toUtf8(_data[2]), "ETH"); + }); + + it("Should alter the old storage", async() => { + await I_MRProxied.addMoreTags(3, ["DAI", "USDTiered"], {from: account_polymath}); + let _data = await I_MRProxied.getTagByModuleType.call(3); + assert.equal(_data.length, 6, "Should give the updated length"); + }); + }) + + describe("Transfer the ownership of the proxy contract", async() => { + + it("Should change the ownership of the contract -- because of bad owner", async()=> { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_temp}); + } catch(error) { + console.log(` tx -> revert because of bad owner`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the ownership of the contract -- new address should not be 0x", async()=> { + let errorThrown = false; + try { + await I_ModuleRegistryProxy.transferProxyOwnership("0x00000000000000000000000000000000000000", {from: account_polymath}); + } catch(error) { + console.log(` tx -> revert because new owner address should not be 0x`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should change the ownership of the contract", async()=> { + await I_ModuleRegistryProxy.transferProxyOwnership(account_polymath_new, {from: account_polymath}); + let _currentOwner = await I_ModuleRegistryProxy.proxyOwner.call({from: account_polymath_new}); + assert.equal(_currentOwner, account_polymath_new, "Should equal to the new owner"); + }); + + it("Should change the implementation contract and version by the new owner", async() => { + I_ModuleRegistry = await ModuleRegistry.new({from: account_polymath}); + await I_ModuleRegistryProxy.upgradeTo("1.2.0", I_ModuleRegistry.address, {from: account_polymath_new}); + let c = OwnedUpgradeabilityProxy.at(I_ModuleRegistryProxy.address); + assert.equal((web3.utils.toAscii(await readStorage(c.address, 11)).replace(/\u0000/g, '')).replace(/\n/, ''), "1.2.0", "Version mis-match"); + assert.equal(await readStorage(c.address, 12), I_ModuleRegistry.address, "Implemnted address is not matched"); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + }); + }) + + +})