From 0839c14669cd1fb7d4bbbf4aac4387749d39e07e Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 18 Sep 2018 22:08:35 +0530 Subject: [PATCH 01/18] intial verrsion of MR --- contracts/ModuleRegistryV2.sol | 267 ++++++++++++++++++++++++ contracts/proxy/ModuleRegistryProxy.sol | 15 ++ contracts/storage/EternalStorage.sol | 24 +++ migrations/2_deploy_contracts.js | 22 ++ test/helpers/encodeCall.js | 7 + 5 files changed, 335 insertions(+) create mode 100644 contracts/ModuleRegistryV2.sol create mode 100644 contracts/proxy/ModuleRegistryProxy.sol diff --git a/contracts/ModuleRegistryV2.sol b/contracts/ModuleRegistryV2.sol new file mode 100644 index 000000000..5426dbbe1 --- /dev/null +++ b/contracts/ModuleRegistryV2.sol @@ -0,0 +1,267 @@ +pragma solidity ^0.4.24; + +import "./interfaces/IModuleRegistry.sol"; +import "./interfaces/IModuleFactory.sol"; +import "./interfaces/ISecurityTokenRegistry.sol"; +import "./interfaces/IFeatureRegistry.sol"; +import "./interfaces/IERC20.sol"; +import "./storage/EternalStorage.sol"; +import "./libraries/Encoder.sol"; +import "./interfaces/IOwner.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 +*/ +contract ModuleRegistryV2 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 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; + */ + + /////////// + // Events + ////////// + + // Emit when ecosystem get paused + event Pause(uint256 _timestammp); + // Emit when ecosystem get unpaused + event Unpause(uint256 _timestamp); + // 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); + + /////////////// + //// 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 + * @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(getAddress(Encoder.getKey('securityTokenRegistry'))).isSecurityToken(msg.sender)) { + if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { + require(getBool(Encoder.getKey('verified', _moduleFactory)) || IOwner(_moduleFactory).owner() == IOwner(msg.sender).owner(), + "ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); + } else { + require(getBool(Encoder.getKey('verified', _moduleFactory)), "ModuleFactory must be verified"); + } + require(getUint(Encoder.getKey('registry',_moduleFactory)) != 0, "ModuleFactory type should not be 0"); + pushArray(Encoder.getKey('reputation', _moduleFactory), msg.sender); + emit LogModuleUsed(_moduleFactory, msg.sender); + } + } + + /** + * @notice Called by moduleFactory owner to register new modules for SecurityToken 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(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"); + set(Encoder.getKey('registry', _moduleFactory), uint256(moduleType)); + set(Encoder.getKey('moduleListIndex', _moduleFactory), getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length); + pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); + setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); + emit LogModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); + return true; + } + + /** + * @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 + */ + function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { + uint256 moduleType = getUint(Encoder.getKey('registry', _moduleFactory)); + + require(moduleType != 0, "Module factory should be registered"); + require(msg.sender == IOwner(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), + "msg.sender must be moduleFactory owner or registry curator"); + + uint256 index = getUint(Encoder.getKey('moduleListIndex', _moduleFactory)); + uint256 last = getArrayAddress(Encoder.getKey('moduleList', moduleType)).length - 1; + address temp = getArrayAddress(Encoder.getKey('moduleList', moduleType))[last]; + + // pop from array and re-order + if (index != last) { + // moduleList[moduleType][index] = temp; + addressArrayStorage[Encoder.getKey('moduleList', moduleType)][index] = temp; + set(Encoder.getKey('moduleListIndex', temp), index); + } + deleteArrayAddress(Encoder.getKey('moduleList', moduleType), last); + + // 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 LogModuleRemoved (_moduleFactory, msg.sender); + return true; + } + + /** + * @notice Called by Polymath to verify modules for SecurityToken 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 + * @return bool + */ + function verifyModule(address _moduleFactory, bool _verified) external onlyOwner returns(bool) { + //Must already have been registered + require(getUint(Encoder.getKey('registry', _moduleFactory)) != uint256(0), "Module factory should have been already registered"); + set(Encoder.getKey('verified', _moduleFactory), _verified); + emit LogModuleVerified(_moduleFactory, _verified); + return true; + } + + /** + * @notice Add the tag for specified Module Factory + * @param _moduleType Type of module. + * @param _tag List of tags + */ + function addTagByModuleType(uint8 _moduleType, bytes32[] _tag) external onlyOwner { + for (uint8 i = 0; i < _tag.length; 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 + */ + function removeTagByModuleType(uint8 _moduleType, bytes32[] _removedTags) external onlyOwner { + for (uint8 i = 0; i < getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType))).length; i++) { + for (uint8 j = 0; j < _removedTags.length; j++) { + 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 + * @return bytes32 array + */ + function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]) { + 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 + */ + function getReputationOfFactory(address _factoryAddress) external view returns(address[]) { + return getArrayAddress(Encoder.getKey('reputation', _factoryAddress)); + } + + /** + * @notice Use to get the list of addresses of Module factory for a particular type + * @param _moduleType Type of Module + * @return address array thal contains the lis of addresses of module factory contracts. + */ + function getModuleListOfType(uint8 _moduleType) external view returns(address[]) { + return getArrayAddress(Encoder.getKey('moduleList', uint256(_moduleType))); + } + + /** + * @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() 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); + } + + +} 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 dee60aaf8..a4df08208 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 ///////////////////////// diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index dba68a7bf..9d29f1e06 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -6,6 +6,8 @@ const PercentageTransferManagerFactory = artifacts.require('./PercentageTransfer const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') +const ModuleRegistryV2 = artifacts.require('./ModuleRegistryV2.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') @@ -97,6 +99,19 @@ 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 @@ -108,6 +123,13 @@ module.exports = function (deployer, network, accounts) { // 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}); + }).then(() => { + return deployer.deploy(ModuleRegistryV2, {from: PolymathAccount}); + }).then(() => { + return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); + }).then(() => { + let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [PolymathRegistry.address, PolymathAccount]); + ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistryV2.address, bytesProxyMR, {from: PolymathAccount}); }).then(() => { return ModuleRegistry.deployed().then((_moduleRegistry) => { moduleRegistry = _moduleRegistry; diff --git a/test/helpers/encodeCall.js b/test/helpers/encodeCall.js index d3dac7f78..da6a91f56 100644 --- a/test/helpers/encodeCall.js +++ b/test/helpers/encodeCall.js @@ -6,3 +6,10 @@ export function encodeProxyCall(values) { const params = abi.rawEncode(parameters, values).toString('hex'); return '0x' + methodId + params; } + +export function encodeMRProxyCall(values) { + const parameters = ['address', 'address']; + const methodId = abi.methodID("initialize", parameters).toString('hex'); + const params = abi.rawEncode(parameters, values).toString('hex'); + return '0x' + methodId + params; +} From 345b5d22fec4f846b2cc33a1dce728bac4f24a1c Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 19 Sep 2018 01:01:31 +0530 Subject: [PATCH 02/18] fix the migrations and adding the updater functionality in the MR --- contracts/ModuleRegistry.sol | 208 +++++++++++----- contracts/ModuleRegistryV2.sol | 267 --------------------- contracts/OldModuleRegistry.sol | 200 +++++++++++++++ contracts/PolymathRegistry.sol | 4 +- contracts/interfaces/IPolymathRegistry.sol | 14 ++ migrations/2_deploy_contracts.js | 19 +- 6 files changed, 369 insertions(+), 343 deletions(-) delete mode 100644 contracts/ModuleRegistryV2.sol create mode 100644 contracts/OldModuleRegistry.sol create mode 100644 contracts/interfaces/IPolymathRegistry.sol diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 9878da565..3f43a2d40 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -3,30 +3,41 @@ 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 "./storage/EternalStorage.sol"; +import "./libraries/Encoder.sol"; +import "./interfaces/IOwner.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 */ -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; +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 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; + */ + + /////////// + // Events + ////////// + // Emit when ecosystem get paused + event Pause(uint256 _timestammp); + // Emit when ecosystem get unpaused + event Unpause(uint256 _timestamp); // 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 @@ -36,9 +47,51 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo // 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) + /////////////// + //// 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); + _updateFromRegistry(_polymathRegistry); + set(Encoder.getKey("initialised"), true); } /** @@ -50,15 +103,15 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo */ 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)) || IOwner(_moduleFactory).owner() == IOwner(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); + require(getUint(Encoder.getKey('registry',_moduleFactory)) != 0, "ModuleFactory type should not be 0"); + pushArray(Encoder.getKey('reputation', _moduleFactory), msg.sender); emit LogModuleUsed(_moduleFactory, msg.sender); } } @@ -69,15 +122,15 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo * @return bool */ function registerModule(address _moduleFactory) external whenNotPaused returns(bool) { - require(registry[_moduleFactory] == 0, "Module factory should not be pre-registered"); + 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()); + set(Encoder.getKey('registry', _moduleFactory), uint256(moduleType)); + set(Encoder.getKey('moduleListIndex', _moduleFactory), getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length); + pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); + setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); + emit LogModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); return true; } @@ -87,29 +140,32 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo * @return bool */ function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { - uint8 moduleType = registry[_moduleFactory]; + 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 == IOwner(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), + "msg.sender must be moduleFactory 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; + addressArrayStorage[Encoder.getKey('moduleList', moduleType)][index] = temp; + set(Encoder.getKey('moduleListIndex', temp), index); } - delete moduleList[moduleType][last]; - moduleList[moduleType].length--; - - delete registry[_moduleFactory]; - delete reputation[_moduleFactory]; - delete verified[_moduleFactory]; - delete moduleListIndex[_moduleFactory]; + deleteArrayAddress(Encoder.getKey('moduleList', moduleType), last); + // 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 LogModuleRemoved (_moduleFactory, msg.sender); return true; } @@ -123,8 +179,8 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo */ 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; + require(getUint(Encoder.getKey('registry', _moduleFactory)) != uint256(0), "Module factory should have been already registered"); + set(Encoder.getKey('verified', _moduleFactory), _verified); emit LogModuleVerified(_moduleFactory, _verified); return true; } @@ -136,7 +192,7 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo */ 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]); } } @@ -146,10 +202,10 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo * @param _removedTags List of tags */ 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)); } } } @@ -161,7 +217,7 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo * @return bytes32 array */ function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]) { - return availableTags[_moduleType]; + return getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType))); } /** @@ -170,7 +226,7 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo * @return address array which have the list of securityToken's uses that module factory */ function getReputationOfFactory(address _factoryAddress) external view returns(address[]) { - return reputation[_factoryAddress]; + return getArrayAddress(Encoder.getKey('reputation', _factoryAddress)); } /** @@ -179,22 +235,50 @@ contract ModuleRegistry is IModuleRegistry, Pausable, RegistryUpdater, ReclaimTo * @return address array thal contains the lis 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 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 unpause() public onlyOwner { - _unpause(); + function pause() external whenNotPaused onlyOwner { + set(Encoder.getKey("paused"), true); + emit Pause(now); } /** - * @notice unpause registration function + * @notice called by the owner to unpause, returns to normal state */ - function pause() public onlyOwner { - _pause(); + function unpause() external whenPaused onlyOwner { + set(Encoder.getKey("paused"), false); + emit Unpause(now); } + /** + * @notice Use to get the latest contract address of the regstries + */ + + function updateFromRegistry() onlyOwner external { + address _polymathRegistry = getAddress(Encoder.getKey('polymathRegistry')); + _updateFromRegistry(_polymathRegistry); + } + + function _updateFromRegistry(address _polymathRegistry) internal { + set(Encoder.getKey('moduleRegistry'), IPolymathRegistry(_polymathRegistry).getAddress("ModuleRegistry")); + 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/ModuleRegistryV2.sol b/contracts/ModuleRegistryV2.sol deleted file mode 100644 index 5426dbbe1..000000000 --- a/contracts/ModuleRegistryV2.sol +++ /dev/null @@ -1,267 +0,0 @@ -pragma solidity ^0.4.24; - -import "./interfaces/IModuleRegistry.sol"; -import "./interfaces/IModuleFactory.sol"; -import "./interfaces/ISecurityTokenRegistry.sol"; -import "./interfaces/IFeatureRegistry.sol"; -import "./interfaces/IERC20.sol"; -import "./storage/EternalStorage.sol"; -import "./libraries/Encoder.sol"; -import "./interfaces/IOwner.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 -*/ -contract ModuleRegistryV2 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 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; - */ - - /////////// - // Events - ////////// - - // Emit when ecosystem get paused - event Pause(uint256 _timestammp); - // Emit when ecosystem get unpaused - event Unpause(uint256 _timestamp); - // 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); - - /////////////// - //// 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 - * @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(getAddress(Encoder.getKey('securityTokenRegistry'))).isSecurityToken(msg.sender)) { - if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { - require(getBool(Encoder.getKey('verified', _moduleFactory)) || IOwner(_moduleFactory).owner() == IOwner(msg.sender).owner(), - "ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); - } else { - require(getBool(Encoder.getKey('verified', _moduleFactory)), "ModuleFactory must be verified"); - } - require(getUint(Encoder.getKey('registry',_moduleFactory)) != 0, "ModuleFactory type should not be 0"); - pushArray(Encoder.getKey('reputation', _moduleFactory), msg.sender); - emit LogModuleUsed(_moduleFactory, msg.sender); - } - } - - /** - * @notice Called by moduleFactory owner to register new modules for SecurityToken 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(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"); - set(Encoder.getKey('registry', _moduleFactory), uint256(moduleType)); - set(Encoder.getKey('moduleListIndex', _moduleFactory), getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length); - pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); - setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); - emit LogModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); - return true; - } - - /** - * @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 - */ - function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { - uint256 moduleType = getUint(Encoder.getKey('registry', _moduleFactory)); - - require(moduleType != 0, "Module factory should be registered"); - require(msg.sender == IOwner(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), - "msg.sender must be moduleFactory owner or registry curator"); - - uint256 index = getUint(Encoder.getKey('moduleListIndex', _moduleFactory)); - uint256 last = getArrayAddress(Encoder.getKey('moduleList', moduleType)).length - 1; - address temp = getArrayAddress(Encoder.getKey('moduleList', moduleType))[last]; - - // pop from array and re-order - if (index != last) { - // moduleList[moduleType][index] = temp; - addressArrayStorage[Encoder.getKey('moduleList', moduleType)][index] = temp; - set(Encoder.getKey('moduleListIndex', temp), index); - } - deleteArrayAddress(Encoder.getKey('moduleList', moduleType), last); - - // 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 LogModuleRemoved (_moduleFactory, msg.sender); - return true; - } - - /** - * @notice Called by Polymath to verify modules for SecurityToken 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 - * @return bool - */ - function verifyModule(address _moduleFactory, bool _verified) external onlyOwner returns(bool) { - //Must already have been registered - require(getUint(Encoder.getKey('registry', _moduleFactory)) != uint256(0), "Module factory should have been already registered"); - set(Encoder.getKey('verified', _moduleFactory), _verified); - emit LogModuleVerified(_moduleFactory, _verified); - return true; - } - - /** - * @notice Add the tag for specified Module Factory - * @param _moduleType Type of module. - * @param _tag List of tags - */ - function addTagByModuleType(uint8 _moduleType, bytes32[] _tag) external onlyOwner { - for (uint8 i = 0; i < _tag.length; 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 - */ - function removeTagByModuleType(uint8 _moduleType, bytes32[] _removedTags) external onlyOwner { - for (uint8 i = 0; i < getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType))).length; i++) { - for (uint8 j = 0; j < _removedTags.length; j++) { - 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 - * @return bytes32 array - */ - function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]) { - 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 - */ - function getReputationOfFactory(address _factoryAddress) external view returns(address[]) { - return getArrayAddress(Encoder.getKey('reputation', _factoryAddress)); - } - - /** - * @notice Use to get the list of addresses of Module factory for a particular type - * @param _moduleType Type of Module - * @return address array thal contains the lis of addresses of module factory contracts. - */ - function getModuleListOfType(uint8 _moduleType) external view returns(address[]) { - return getArrayAddress(Encoder.getKey('moduleList', uint256(_moduleType))); - } - - /** - * @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() 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); - } - - -} diff --git a/contracts/OldModuleRegistry.sol b/contracts/OldModuleRegistry.sol new file mode 100644 index 000000000..aa075e976 --- /dev/null +++ b/contracts/OldModuleRegistry.sol @@ -0,0 +1,200 @@ +pragma solidity ^0.4.24; + +import "./interfaces/IModuleRegistry.sol"; +import "./interfaces/IModuleFactory.sol"; +import "./interfaces/ISecurityTokenRegistry.sol"; +import "./interfaces/IFeatureRegistry.sol"; +import "./Pausable.sol"; +import "./RegistryUpdater.sol"; +import "./ReclaimTokens.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 +*/ +contract OldModuleRegistry 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) + { + } + + /** + * @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 + * @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"); + } else { + require(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); + } + } + + /** + * @notice Called by moduleFactory owner to register new modules for SecurityToken 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"); + 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; + } + + /** + * @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 + */ + function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { + uint8 moduleType = 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"); + + uint8 index = moduleListIndex[_moduleFactory]; + uint8 last = uint8(moduleList[moduleType].length - 1); + address temp = moduleList[moduleType][last]; + + // pop from array and re-order + if (index != last) { + moduleList[moduleType][index] = temp; + moduleListIndex[temp] = index; + } + delete moduleList[moduleType][last]; + moduleList[moduleType].length--; + + delete registry[_moduleFactory]; + delete reputation[_moduleFactory]; + delete verified[_moduleFactory]; + delete moduleListIndex[_moduleFactory]; + + emit LogModuleRemoved (_moduleFactory, msg.sender); + return true; + } + + /** + * @notice Called by Polymath to verify modules for SecurityToken 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 + * @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); + return true; + } + + /** + * @notice Add the tag for specified Module Factory + * @param _moduleType Type of module. + * @param _tag List of tags + */ + function addTagByModuleType(uint8 _moduleType, bytes32[] _tag) external onlyOwner { + for (uint8 i = 0; i < _tag.length; i++) { + availableTags[_moduleType].push(_tag[i]); + } + } + + /** + * @notice remove the tag for specified Module Factory + * @param _moduleType Type of module. + * @param _removedTags List of tags + */ + function removeTagByModuleType(uint8 _moduleType, bytes32[] _removedTags) external onlyOwner { + for (uint8 i = 0; i < availableTags[_moduleType].length; i++) { + for (uint8 j = 0; j < _removedTags.length; j++) { + if (availableTags[_moduleType][i] == _removedTags[j]) { + delete availableTags[_moduleType][i]; + } + } + } + } + + /** + * @notice Use to get all the tags releated to the functionality of the Module Factory. + * @param _moduleType Type of module + * @return bytes32 array + */ + function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]) { + return availableTags[_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 + */ + function getReputationOfFactory(address _factoryAddress) external view returns(address[]) { + return reputation[_factoryAddress]; + } + + /** + * @notice Use to get the list of addresses of Module factory for a particular type + * @param _moduleType Type of Module + * @return address array thal contains the lis of addresses of module factory contracts. + */ + function getModuleListOfType(uint8 _moduleType) external view returns(address[]) { + return moduleList[_moduleType]; + } + + /** + * @notice pause registration function + */ + function unpause() public onlyOwner { + _unpause(); + } + + /** + * @notice unpause registration function + */ + function pause() public onlyOwner { + _pause(); + } + + +} diff --git a/contracts/PolymathRegistry.sol b/contracts/PolymathRegistry.sol index 847659b81..dca66ebf0 100644 --- a/contracts/PolymathRegistry.sol +++ b/contracts/PolymathRegistry.sol @@ -16,7 +16,7 @@ contract PolymathRegistry is ReclaimTokens { * @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,7 +27,7 @@ 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); storedAddresses[key] = _newAddress; 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/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 9d29f1e06..81fe41a45 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -1,4 +1,3 @@ -const ModuleRegistry = artifacts.require('./ModuleRegistry.sol') const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') @@ -6,7 +5,7 @@ const PercentageTransferManagerFactory = artifacts.require('./PercentageTransfer const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') -const ModuleRegistryV2 = artifacts.require('./ModuleRegistryV2.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') @@ -121,20 +120,16 @@ const functionSignatureProxyMR = { 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}); - }).then(() => { - return deployer.deploy(ModuleRegistryV2, {from: PolymathAccount}); + return deployer.deploy(ModuleRegistry, {from: PolymathAccount}); }).then(() => { return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); }).then(() => { let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [PolymathRegistry.address, PolymathAccount]); - ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistryV2.address, bytesProxyMR, {from: PolymathAccount}); + ModuleRegistryProxy.at(ModuleRegistryProxy.address).upgradeToAndCall("1.0.0", ModuleRegistry.address, bytesProxyMR, {from: PolymathAccount}); }).then(() => { - return ModuleRegistry.deployed().then((_moduleRegistry) => { - moduleRegistry = _moduleRegistry; + 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) @@ -248,7 +243,7 @@ const functionSignatureProxyMR = { 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}) @@ -285,6 +280,7 @@ const functionSignatureProxyMR = { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${moduleRegistry.address} FeatureRegistry: ${FeatureRegistry.address} ETHOracle: ${ETHOracle} @@ -311,5 +307,4 @@ const functionSignatureProxyMR = { }); }); }); -}); } From 119a8371b3efcc94c921a7bac8dc38c89a4ac35a Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 19 Sep 2018 17:32:57 +0530 Subject: [PATCH 03/18] add getter --- contracts/ModuleRegistry.sol | 48 ++++++++++--- contracts/interfaces/IModuleRegistry.sol | 8 +++ test/k_module_registry.js | 92 ++++++++++++------------ 3 files changed, 93 insertions(+), 55 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 3f43a2d40..4404d87fc 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -18,14 +18,19 @@ 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 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; */ @@ -90,7 +95,6 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { require(_owner != address(0) && _polymathRegistry != address(0), "0x address is in-valid"); set(Encoder.getKey("polymathRegistry"), _polymathRegistry); set(Encoder.getKey("owner"), _owner); - _updateFromRegistry(_polymathRegistry); set(Encoder.getKey("initialised"), true); } @@ -232,12 +236,46 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { /** * @notice Use to get the list of addresses of Module factory for 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 getArrayAddress(Encoder.getKey('moduleList', uint256(_moduleType))); } + /** + * @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[]) { + 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 (IOwner(_addressList[i]).owner() == IOwner(_securityToken).owner()) + counter++; + } + else if (getBool(Encoder.getKey('verified', _addressList[i]))) { + counter ++; + } + } + address[] memory _tempArray = new address[](counter); + counter = 0; + for (uint256 j = 0; j < _tempArray.length; j++) { + if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { + if (IOwner(_addressList[j]).owner() == IOwner(_securityToken).owner()) + _tempArray[counter] = _addressList[j]; + counter ++; + } + else if (getBool(Encoder.getKey('verified', _addressList[j]))) { + _tempArray[counter] = _addressList[j]; + counter ++; + } + } + } + /** * @notice Reclaim all ERC20Basic compatible tokens * @param _tokenContract The address of the token contract @@ -268,14 +306,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { /** * @notice Use to get the latest contract address of the regstries */ - function updateFromRegistry() onlyOwner external { address _polymathRegistry = getAddress(Encoder.getKey('polymathRegistry')); - _updateFromRegistry(_polymathRegistry); - } - - function _updateFromRegistry(address _polymathRegistry) internal { - set(Encoder.getKey('moduleRegistry'), IPolymathRegistry(_polymathRegistry).getAddress("ModuleRegistry")); 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/interfaces/IModuleRegistry.sol b/contracts/interfaces/IModuleRegistry.sol index 972b1dc9f..3b8367dda 100644 --- a/contracts/interfaces/IModuleRegistry.sol +++ b/contracts/interfaces/IModuleRegistry.sol @@ -67,4 +67,12 @@ 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[]); + } diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 4ffe2ecf6..62ef2533f 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 { encodeProxyCall, encodeMRProxyCall } 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'); @@ -51,6 +52,7 @@ contract('ModuleRegistry', accounts => { let I_SecurityTokenRegistryProxy; let I_GeneralPermissionManager; let I_GeneralTransferManager; + let I_ModuleRegistryProxy; let I_ModuleRegistry; let I_TickerRegistry; let I_FeatureRegistry; @@ -58,6 +60,7 @@ contract('ModuleRegistry', accounts => { let I_CappedSTOFactory1; let I_CappedSTOFactory2; let I_STFactory; + let I_MRProxied; let I_SecurityToken; let I_STRProxied; let I_CappedSTO; @@ -91,6 +94,7 @@ contract('ModuleRegistry', accounts => { const cap = new BigNumber(10000).times(new BigNumber(10).pow(18)); const rate = 1000; const fundRaiseType = [0]; + const functionSignature = { name: 'configure', type: 'function', @@ -137,16 +141,26 @@ contract('ModuleRegistry', accounts => { 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 FeatureRegistry + + I_FeatureRegistry = await FeatureRegistry.new( + I_PolymathRegistry.address, + { + from: account_polymath + }); + + await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); + // STEP 2: Deploy the ModuleRegistry + + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); - I_ModuleRegistry = await ModuleRegistry.new(I_PolymathRegistry.address, {from:account_polymath}); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistry.address, {from: account_polymath}); + let bytesMRProxy = encodeMRProxyCall([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" - ); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); // STEP 2: Deploy the GeneralTransferManagerFactory @@ -182,15 +196,7 @@ contract('ModuleRegistry', accounts => { 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(), @@ -199,8 +205,8 @@ 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("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -209,6 +215,7 @@ contract('ModuleRegistry', accounts => { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} STFactory: ${STFactory.address} @@ -221,21 +228,12 @@ contract('ModuleRegistry', accounts => { 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(); + let _owner = await I_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); 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( @@ -276,8 +274,8 @@ contract('ModuleRegistry', accounts => { 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 }); + await I_MRProxied.pause({ from: account_polymath}); + await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); } catch(error) { console.log(` tx revert -> Registration is paused`.grey); errorThrown = true; @@ -287,8 +285,8 @@ contract('ModuleRegistry', accounts => { }); 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 }); + await I_MRProxied.unpause({ from: account_polymath}); + let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); assert.equal( tx.logs[0].args._moduleFactory, @@ -298,7 +296,7 @@ contract('ModuleRegistry', accounts => { assert.equal(tx.logs[0].args._owner, account_polymath); - tx = await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + tx = await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); assert.equal( tx.logs[0].args._moduleFactory, @@ -308,7 +306,7 @@ contract('ModuleRegistry', accounts => { assert.equal(tx.logs[0].args._owner, account_polymath); - tx = await I_ModuleRegistry.registerModule(I_CappedSTOFactory1.address, { from: account_polymath }); + tx = await I_MRProxied.registerModule(I_CappedSTOFactory1.address, { from: account_polymath }); assert.equal( tx.logs[0].args._moduleFactory, @@ -323,7 +321,7 @@ contract('ModuleRegistry', accounts => { it("Should fail in registering the same module again", async() => { let errorThrown = false; try { - await I_ModuleRegistry.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); + await I_MRProxied.registerModule(I_GeneralPermissionManagerFactory.address, { from: account_polymath }); } catch(error) { console.log(` tx revert -> Already Registered Module factory`.grey); errorThrown = true; @@ -335,7 +333,7 @@ contract('ModuleRegistry', accounts => { it("Should fail in registering the module-- type = 0", async() => { let errorThrown = false; try { - await I_ModuleRegistry.registerModule(I_MockFactory.address, { from: account_polymath }); + await I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); } catch(error) { console.log(` tx revert -> Module factory of 0 type`.grey); errorThrown = true; @@ -343,7 +341,7 @@ contract('ModuleRegistry', accounts => { } assert.ok(errorThrown, message); }); - }); + }); describe("Test cases for verify module", async() => { @@ -403,7 +401,7 @@ contract('ModuleRegistry', accounts => { 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 }); + let tx = await I_MRProxied.verifyModule(I_GeneralTransferManagerFactory.address, true, { from: account_polymath }); assert.equal( tx.logs[0].args._moduleFactory, I_GeneralTransferManagerFactory.address, @@ -436,9 +434,9 @@ contract('ModuleRegistry', accounts => { 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_PolymathRegistry.changeAddress("SecurityTokenRegistry", I_SecurityTokenRegistryProxy.address, {from: account_polymath}); - await I_ModuleRegistry.updateFromRegistry({from: account_polymath}); + await I_MRProxied.updateFromRegistry({from: account_polymath}); }); }); @@ -448,7 +446,7 @@ contract('ModuleRegistry', accounts => { 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}); + 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; @@ -458,15 +456,15 @@ contract('ModuleRegistry', accounts => { }); 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); + 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"); }); 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}); + 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; @@ -476,8 +474,8 @@ contract('ModuleRegistry', accounts => { }); 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); + 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, ''),""); }); From 793eea2499656a33914f648b6fb3a5a58a82f07a Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 21 Sep 2018 13:03:12 +0530 Subject: [PATCH 04/18] add the versioning concept into the modules --- contracts/ModuleRegistry.sol | 6 + contracts/SecurityTokenRegistry.sol | 40 ++++- contracts/interfaces/IModuleFactory.sol | 19 +++ .../interfaces/ISecurityTokenRegistry.sol | 12 +- contracts/libraries/VersionUtils.sol | 140 ++++++++++++++++++ contracts/mocks/MockFactory.sol | 2 + contracts/mocks/TestSTOFactory.sol | 2 + .../ERC20DividendCheckpointFactory.sol | 2 + .../EtherDividendCheckpointFactory.sol | 2 + contracts/modules/ModuleFactory.sol | 41 +++++ .../GeneralPermissionManagerFactory.sol | 2 + contracts/modules/STO/CappedSTOFactory.sol | 2 + contracts/modules/STO/DummySTOFactory.sol | 2 + contracts/modules/STO/PreSaleSTOFactory.sol | 2 + contracts/modules/STO/USDTieredSTOFactory.sol | 2 + .../CountTransferManagerFactory.sol | 2 + .../GeneralTransferManagerFactory.sol | 2 + .../ManualApprovalTransferManagerFactory.sol | 2 + .../PercentageTransferManagerFactory.sol | 2 + 19 files changed, 273 insertions(+), 11 deletions(-) create mode 100644 contracts/libraries/VersionUtils.sol diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 4404d87fc..cf849b265 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -6,6 +6,7 @@ import "./interfaces/ISecurityTokenRegistry.sol"; import "./interfaces/IPolymathRegistry.sol"; import "./interfaces/IFeatureRegistry.sol"; import "./interfaces/IERC20.sol"; +import "./libraries/VersionUtils.sol"; import "./storage/EternalStorage.sol"; import "./libraries/Encoder.sol"; import "./interfaces/IOwner.sol"; @@ -114,6 +115,11 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } else { require(getBool(Encoder.getKey('verified', _moduleFactory)), "ModuleFactory must be verified"); } + uint8[] memory _latestVersion = ISecurityTokenRegistry(getAddress(Encoder.getKey('securityTokenRegistry'))).getProtocolVersion(); + uint8[] memory _lowerBound = IModuleFactory(_moduleFactory).getLowerSTVersionBounds(); + uint8[] memory _upperBound = IModuleFactory(_moduleFactory).getUpperSTVersionBounds(); + require(VersionUtils.compareLowerBound(_lowerBound, _latestVersion), "Should not below the lower bound of ST"); + require(VersionUtils.compareUpperBound(_upperBound, _latestVersion), "Should not above the upper bound of ST"); require(getUint(Encoder.getKey('registry',_moduleFactory)) != 0, "ModuleFactory type should not be 0"); pushArray(Encoder.getKey('reputation', _moduleFactory), msg.sender); emit LogModuleUsed(_moduleFactory, msg.sender); diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 3970a3bff..038adae80 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 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; @@ -31,6 +33,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; @@ -110,7 +119,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { 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(1)); set(Encoder.getKey("initialised"), true); } @@ -523,10 +532,12 @@ 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 Address of the proxy. - * @param _version new version of the proxy which is used to deploy the securityToken. + * @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); } /** @@ -534,16 +545,29 @@ 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. */ - 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 Get 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..81a540e96 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -73,9 +73,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(bytes32 _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/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 2827e4824..ada0a1217 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 @@ -96,4 +98,8 @@ interface ISecurityTokenRegistry { */ function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool); + /** + * @notice get Protocol version + */ + function getProtocolVersion() public view returns(uint8[]); } diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol new file mode 100644 index 000000000..72461c3c1 --- /dev/null +++ b/contracts/libraries/VersionUtils.sol @@ -0,0 +1,140 @@ +pragma solidity ^0.4.24; + +library VersionUtils { + + /** + * @notice This function use to validate the inputted version + * @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) public pure returns(bool) { + require(_current.length == _new.length); + 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) public pure returns(bool) { + require(_version1.length == _version2.length); + uint counter = 0; + for (uint8 j = 0; j< _version1.length; j++) { + if (_version1[i] == 0) + counter ++; + } + if (counter != _version1.length) { + counter = 0; + for (uint8 i = 0; i < _version1.length; i++) { + if (i == 0) { + if (_version2[i] > _version1[i]) + return true; + else if (_version2[i] < _version1[i]) + return false; + } 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) public pure returns(bool) { + require(_version1.length == _version2.length); + uint counter = 0; + for (uint8 j = 0; j< _version1.length; j++) { + if (_version1[i] == 0) + counter ++; + } + if (counter != _version1.length) { + counter = 0; + for (uint8 i = 0; i < _version1.length; i++) { + if (i == 0) { + if (_version1[i] > _version2[i]) + return true; + else if (_version1[i] < _version2[i]) + return false; + } 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) public 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) public pure returns (uint8[]) { + uint8[] memory _unpackVersion = new uint8[](3); + _unpackVersion[0] = uint8(_packedVersion >> 16); + _unpackVersion[1] = uint8(_packedVersion >> 8); + _unpackVersion[2] = uint8(_packedVersion); + } + + +} \ No newline at end of file diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index f1840a793..375dd562c 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index 683a336dc..eb1da394b 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("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..26bb5e44c 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 90e816d43..6e9987869 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index 8e8a6a5e1..d39e352bc 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; + // @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(bytes32 => uint24) compatibleSTVersionRange; + 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); + event ChangeSTVersionBound(bytes32 _boundType, uint8 _major, uint8 _minor, uint8 _patch); /** * @notice Constructor @@ -99,4 +108,36 @@ 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(bytes32 _boundType, uint8[] _newVersion) external onlyOwner { + require(_boundType == bytes32("lowerBound") || _boundType == bytes32("upperBound")); + require(_newVersion.length == 3); + if (compatibleSTVersionRange[_boundType] != 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[bytes32("lowerBound")]); + } + + /** + * @notice use to get the upper bound + * @return upper bound + */ + function getUpperSTVersionBounds() external view returns(uint8[]) { + return VersionUtils.unpack(compatibleSTVersionRange[bytes32("upperBound")]); + } + } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index b6bb29677..5a93fc21c 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index d47fca382..ff3c176b1 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index d34ef8b38..a4952ec0e 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** * @notice used to launch the Module with the help of factory diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index bb4163ecc..05e6efc36 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4e0c134da..4756835ef 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -20,6 +20,8 @@ contract USDTieredSTOFactory is ModuleFactory { name = "USDTieredSTO"; title = "USD Tiered STO"; description = "USD Tiered STO"; + compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index 3e88f4b7e..c70e1356b 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index 4a15c47dc..0caee1dc6 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 00621fd36..b21db4a1c 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 728681792..d0f46439e 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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** From 05ae051aa87344c9fda9184a43a8cc5c781acb38 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 21 Sep 2018 17:31:22 +0530 Subject: [PATCH 05/18] remove bug from the library --- contracts/libraries/VersionUtils.sol | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 72461c3c1..365e8209d 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -1,5 +1,9 @@ pragma solidity ^0.4.24; +/** + * @Title Helper library use to compare or validate the semantic versions + */ + library VersionUtils { /** @@ -58,17 +62,12 @@ library VersionUtils { if (counter != _version1.length) { counter = 0; for (uint8 i = 0; i < _version1.length; i++) { - if (i == 0) { if (_version2[i] > _version1[i]) return true; else if (_version2[i] < _version1[i]) return false; - } else { - if (_version2[i] < _version1[i]) - return false; else counter++; - } } if (counter == _version1.length - 1) return true; @@ -94,17 +93,12 @@ library VersionUtils { if (counter != _version1.length) { counter = 0; for (uint8 i = 0; i < _version1.length; i++) { - if (i == 0) { if (_version1[i] > _version2[i]) return true; else if (_version1[i] < _version2[i]) return false; - } else { - if (_version1[i] < _version2[i]) - return false; else counter++; - } } if (counter == _version1.length - 1) return true; From 057ba09d57dbb058e822f214ab5b82e28fa9abd6 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 21 Sep 2018 17:43:01 +0530 Subject: [PATCH 06/18] small fix --- contracts/libraries/VersionUtils.sol | 2 +- contracts/modules/ModuleFactory.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 365e8209d..19b58b33e 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; /** - * @Title Helper library use to compare or validate the semantic versions + * @title Helper library use to compare or validate the semantic versions */ library VersionUtils { diff --git a/contracts/modules/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index d39e352bc..a29046bc6 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -116,7 +116,7 @@ contract ModuleFactory is IModuleFactory, Ownable { function changeSTVersionBounds(bytes32 _boundType, uint8[] _newVersion) external onlyOwner { require(_boundType == bytes32("lowerBound") || _boundType == bytes32("upperBound")); require(_newVersion.length == 3); - if (compatibleSTVersionRange[_boundType] != 0) { + if (compatibleSTVersionRange[_boundType] != uint24(0)) { uint8[] memory _currentVersion = VersionUtils.unpack(compatibleSTVersionRange[_boundType]); require(VersionUtils.isValidVersion(_currentVersion, _newVersion), "Failed because of in-valid version"); } From f0846f6295c7ec850562daa3ec4af085633a71ad Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 21 Sep 2018 18:33:54 +0530 Subject: [PATCH 07/18] remove the Log prefix from the name of the event --- CHANGELOG.md | 3 +- contracts/FeatureRegistry.sol | 4 +- contracts/ModuleRegistry.sol | 16 +++--- contracts/PolymathRegistry.sol | 4 +- contracts/SecurityTokenRegistry.sol | 34 +++++------ contracts/interfaces/IModuleFactory.sol | 8 +-- .../ERC20DividendCheckpointFactory.sol | 2 +- .../EtherDividendCheckpointFactory.sol | 2 +- contracts/modules/ModuleFactory.sol | 14 ++--- .../GeneralPermissionManager.sol | 8 +-- .../GeneralPermissionManagerFactory.sol | 2 +- contracts/modules/STO/CappedSTOFactory.sol | 2 +- contracts/modules/STO/DummySTO.sol | 4 +- contracts/modules/STO/DummySTOFactory.sol | 2 +- contracts/modules/STO/PreSaleSTOFactory.sol | 2 +- contracts/modules/STO/USDTieredSTOFactory.sol | 2 +- .../TransferManager/CountTransferManager.sol | 4 +- .../CountTransferManagerFactory.sol | 2 +- .../GeneralTransferManager.sol | 30 +++++----- .../GeneralTransferManagerFactory.sol | 2 +- .../ManualApprovalTransferManager.sol | 16 +++--- .../ManualApprovalTransferManagerFactory.sol | 2 +- .../PercentageTransferManager.sol | 8 +-- .../PercentageTransferManagerFactory.sol | 2 +- contracts/tokens/SecurityToken.sol | 56 +++++++++---------- 25 files changed, 116 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fdc35af8..77a155240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,8 @@ All notable changes to this project will be documented in this file. * 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 +* 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 cf849b265..05276f9c4 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -45,13 +45,13 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // Emit when ecosystem get unpaused event Unpause(uint256 _timestamp); // Emit when Module been used by the securityToken - event LogModuleUsed(address indexed _moduleFactory, address indexed _securityToken); + event ModuleUsed(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); + event ModuleRegistered(address indexed _moduleFactory, address indexed _owner); // Emit when the module get verified by the Polymath team - event LogModuleVerified(address indexed _moduleFactory, bool _verified); + event ModuleVerified(address indexed _moduleFactory, bool _verified); // Emit when a moduleFactory is removed by Polymath or moduleFactory owner - event LogModuleRemoved(address indexed _moduleFactory, address indexed _decisionMaker); + event ModuleRemoved(address indexed _moduleFactory, address indexed _decisionMaker); /////////////// //// Modifiers @@ -122,7 +122,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { require(VersionUtils.compareUpperBound(_upperBound, _latestVersion), "Should not above the upper bound of ST"); require(getUint(Encoder.getKey('registry',_moduleFactory)) != 0, "ModuleFactory type should not be 0"); pushArray(Encoder.getKey('reputation', _moduleFactory), msg.sender); - emit LogModuleUsed(_moduleFactory, msg.sender); + emit ModuleUsed(_moduleFactory, msg.sender); } } @@ -140,7 +140,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { set(Encoder.getKey('moduleListIndex', _moduleFactory), getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length); pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); - emit LogModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); + emit ModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); return true; } @@ -176,7 +176,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { set(Encoder.getKey('verified', _moduleFactory), false); // delete moduleListIndex[_moduleFactory]; set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(0)); - emit LogModuleRemoved (_moduleFactory, msg.sender); + emit ModuleRemoved (_moduleFactory, msg.sender); return true; } @@ -191,7 +191,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { //Must already have been registered require(getUint(Encoder.getKey('registry', _moduleFactory)) != uint256(0), "Module factory should have been already registered"); set(Encoder.getKey('verified', _moduleFactory), _verified); - emit LogModuleVerified(_moduleFactory, _verified); + emit ModuleVerified(_moduleFactory, _verified); return true; } diff --git a/contracts/PolymathRegistry.sol b/contracts/PolymathRegistry.sol index dca66ebf0..d33ad68f4 100644 --- a/contracts/PolymathRegistry.sol +++ b/contracts/PolymathRegistry.sol @@ -9,7 +9,7 @@ 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 @@ -29,7 +29,7 @@ contract PolymathRegistry is ReclaimTokens { */ 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 16491443a..06269830e 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -64,21 +64,21 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { // Emit when ecosystem get 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 get 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 get transferred event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // Emit when ownership of the ticker get 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 get 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 of new security token - event LogNewSecurityToken( + event NewSecurityToken( string _ticker, string _name, address indexed _securityTokenAddress, @@ -88,7 +88,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bool _fromAdmin ); // Emit after the ticker registration - event LogRegisterTicker( + event RegisterTicker( address indexed _owner, string _ticker, string _name, @@ -179,7 +179,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); } /** @@ -193,7 +193,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); } /** @@ -217,7 +217,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); } /** @@ -269,7 +269,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); } function _deleteTickerOwnership(address _owner, string _ticker) internal { @@ -289,7 +289,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); } @@ -372,7 +372,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); } /** @@ -394,7 +394,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); } /** @@ -502,7 +502,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); } @@ -512,7 +512,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); } diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 81a540e96..08c1a6276 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, diff --git a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol index 26bb5e44c..e728fe024 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -34,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 6e9987869..079c28ff4 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -34,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 a29046bc6..af09f1357 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -27,10 +27,10 @@ contract ModuleFactory is IModuleFactory, Ownable { // @dev uint24 consists packed value of uint8 _major, uint8 _minor, uint8 _patch mapping(bytes32 => uint24) compatibleSTVersionRange; - 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); + 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(bytes32 _boundType, uint8 _major, uint8 _minor, uint8 _patch); /** @@ -49,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; } @@ -58,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; } @@ -67,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; } 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 5a93fc21c..bbd35c0f3 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -31,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 ff3c176b1..7b54f009a 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -36,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 a4952ec0e..c7f8a465b 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -35,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 05e6efc36..87f2816b4 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -38,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/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4756835ef..67a5a1771 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -36,7 +36,7 @@ contract USDTieredSTOFactory is ModuleFactory { //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == usdTieredSTO.getInitFunction(), "Invalid data"); require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); - emit LogGenerateModuleFromFactory(address(usdTieredSTO), getName(), address(this), msg.sender, setupCost, now); + emit GenerateModuleFromFactory(address(usdTieredSTO), getName(), address(this), msg.sender, setupCost, now); return address(usdTieredSTO); } 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 c70e1356b..e7849849b 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -35,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 0caee1dc6..a896de646 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -32,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 b21db4a1c..0ef126f89 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -34,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 d0f46439e..85319641b 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -35,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/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 1f2867f26..134f6b1d3 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -94,7 +94,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 +105,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[msg.sender].module == msg.sender, "Address mismatch"); @@ -255,7 +255,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 +265,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 +275,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 +286,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 +371,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 +379,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 +389,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 +450,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 +459,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 +600,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 +696,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 +766,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 +778,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr require(!controllerDisabled); controllerDisabled = true; delete controller; - emit LogDisableController(now); + emit DisableController(now); } /** @@ -799,7 +799,7 @@ 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; } From 7a4e9f73a3df743baca8472a81383d6c4fb8f262 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 21 Sep 2018 21:23:35 +0530 Subject: [PATCH 08/18] add proxy for the USDTiered deployment --- contracts/SecurityTokenRegistry.sol | 2 +- contracts/interfaces/IUSDTieredSTOProxy.sol | 26 +++++++++++++++ contracts/libraries/VersionUtils.sol | 10 +++--- .../ProxyFactory/USDTieredSTOProxyFactory.sol | 33 +++++++++++++++++++ contracts/modules/STO/USDTieredSTOFactory.sol | 19 ++++++++--- migrations/2_deploy_contracts.js | 9 ++++- 6 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 contracts/interfaces/IUSDTieredSTOProxy.sol create mode 100644 contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 06269830e..a572f6e98 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -390,7 +390,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_deployedAt != 0 && _owner != address(0), "0 value params not allowed"); string memory ticker = Util.upper(_ticker); require(_securityToken != address(0), "ST address is 0x"); - // If ticker didn't previously exist, registration & expiry time will be set to zero + // If ticker didn't previously exist, registration & expiry time will be set according to the now (current) time _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); diff --git a/contracts/interfaces/IUSDTieredSTOProxy.sol b/contracts/interfaces/IUSDTieredSTOProxy.sol new file mode 100644 index 000000000..c73d811e3 --- /dev/null +++ b/contracts/interfaces/IUSDTieredSTOProxy.sol @@ -0,0 +1,26 @@ +pragma solidity ^0.4.24; + +/** + * @title Interface for security token proxy deployment + */ +interface IUSDTieredSTOProxy { + + /** + * @notice deploys the STO. + */ + function deploySTO(address _securityToken, address _polyAddress) 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); + + /** + * @notice Use to intialize the state variables of the STO contract + * @param _contractAddress Address of the STO contract + * @param _data Data that use to intialize the values + */ + function initialize(address _contractAddress, bytes _data) external returns (bool); +} \ No newline at end of file diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 19b58b33e..c7bca2ff2 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -12,7 +12,7 @@ library VersionUtils { * @param _new Array holds the latest version of the ST * @return bool */ - function isValidVersion(uint8[] _current, uint8[] _new) public pure returns(bool) { + function isValidVersion(uint8[] _current, uint8[] _new) internal pure returns(bool) { require(_current.length == _new.length); bool[] memory _temp = new bool[](_current.length); uint8 counter = 0; @@ -52,7 +52,7 @@ library VersionUtils { * @param _version2 Array holds the latest version of the ST * @return bool */ - function compareLowerBound(uint8[] _version1, uint8[] _version2) public pure returns(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++) { @@ -83,7 +83,7 @@ library VersionUtils { * @param _version2 Array holds the latest version of the ST * @return bool */ - function compareUpperBound(uint8[] _version1, uint8[] _version2) public pure returns(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++) { @@ -115,7 +115,7 @@ library VersionUtils { * @param _minor Minor version * @param _patch Patch version */ - function pack(uint8 _major, uint8 _minor, uint8 _patch) public pure returns(uint24) { + function pack(uint8 _major, uint8 _minor, uint8 _patch) internal pure returns(uint24) { return (uint24(_major) << 16) | (uint24(_minor) << 8) | uint24(_patch); } @@ -123,7 +123,7 @@ library VersionUtils { * @notice Use to convert packed data into uint8 array * @param _packedVersion Packed data */ - function unpack(uint24 _packedVersion) public pure returns (uint8[]) { + function unpack(uint24 _packedVersion) internal pure returns (uint8[]) { uint8[] memory _unpackVersion = new uint8[](3); _unpackVersion[0] = uint8(_packedVersion >> 16); _unpackVersion[1] = uint8(_packedVersion >> 8); diff --git a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol new file mode 100644 index 000000000..e08d99dd3 --- /dev/null +++ b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol @@ -0,0 +1,33 @@ +pragma solidity ^0.4.24; + +import "../USDTieredSTO.sol"; + +contract USDTieredSTOProxyFactory { + + /** + * @notice deploys the STO. + */ + function deploySTO(address _securityToken, address _polyAddress) external returns (address) { + address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _polyAddress); + 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(); + } + + /** + * @notice Use to intialize the state variables of the STO contract + * @param _contractAddress Address of the STO contract + * @param _data Data that use to intialize the values + */ + function initialize(address _contractAddress, bytes _data) external returns (bool) { + return USDTieredSTO(_contractAddress).call(_data); + } + +} \ No newline at end of file diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 67a5a1771..4be2e6691 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,6 +9,8 @@ import "../../libraries/Util.sol"; */ contract USDTieredSTOFactory is ModuleFactory { + address public USDTieredSTOProxyAddress; + /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -32,10 +34,10 @@ contract USDTieredSTOFactory is ModuleFactory { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); //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)); //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == usdTieredSTO.getInitFunction(), "Invalid data"); - require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); + require(Util.getSig(_data) == IUSDTieredSTOProxy(USDTieredSTOProxyAddress).getInitFunction(usdTieredSTO), "Invalid data"); + require(IUSDTieredSTOProxy(USDTieredSTOProxyAddress).initialize(usdTieredSTO, _data), "Unsuccessfull call"); emit GenerateModuleFromFactory(address(usdTieredSTO), getName(), address(this), msg.sender, setupCost, now); return address(usdTieredSTO); } @@ -101,4 +103,13 @@ contract USDTieredSTOFactory is ModuleFactory { return availableTags; } + /** + * @notice Function use to set the proxy address + * @param _proxyAddress Address of the proxy factory contract + */ + function setProxyFactoryAddress(address _proxyAddress) public onlyOwner { + require(_proxyAddress != address(0)); + USDTieredSTOProxyAddress = _proxyAddress; + } + } diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 81fe41a45..38592883b 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -2,6 +2,7 @@ const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol') const GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol') const PercentageTransferManagerFactory = artifacts.require('./PercentageTransferManagerFactory.sol') +const USDTieredSTOProxyFactory = artifacts.require('./USDTieredSTOProxyFactory.sol'); const CountTransferManagerFactory = artifacts.require('./CountTransferManagerFactory.sol') const EtherDividendCheckpointFactory = artifacts.require('./EtherDividendCheckpointFactory.sol') const ERC20DividendCheckpointFactory = artifacts.require('./ERC20DividendCheckpointFactory.sol') @@ -256,9 +257,15 @@ const functionSignatureProxyMR = { // contract, Factory should comes under the verified list of factories or those factories deployed by the securityToken issuers only. // Here it gets verified because it is deployed by the third party account (Polymath Account) not with the issuer accounts. return moduleRegistry.verifyModule(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, {from: PolymathAccount}) + }).then(() => { + // Set proxy factory address into the USDTieredSTOFactory contract + return USDTieredSTOFactory.at(USDTieredSTOFactory.address).setProxyFactoryAddress(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. From 6ce4db0181f8b2ae0d8cccd3fed3d080247396e1 Mon Sep 17 00:00:00 2001 From: satyam Date: Fri, 21 Sep 2018 22:06:17 +0530 Subject: [PATCH 09/18] add restriction --- contracts/modules/STO/USDTieredSTOFactory.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/modules/STO/USDTieredSTOFactory.sol b/contracts/modules/STO/USDTieredSTOFactory.sol index 4be2e6691..b536eb4dd 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -33,6 +33,7 @@ contract USDTieredSTOFactory is ModuleFactory { function deploy(bytes _data) external returns(address) { if(setupCost > 0) require(polyToken.transferFrom(msg.sender, owner, setupCost), "Sufficent Allowance is not provided"); + require(USDTieredSTOProxyAddress != address(0)); //Check valid bytes - can only call module init function address usdTieredSTO = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, address(polyToken)); //Checks that _data is valid (not calling anything it shouldn't) @@ -109,6 +110,7 @@ contract USDTieredSTOFactory is ModuleFactory { */ function setProxyFactoryAddress(address _proxyAddress) public onlyOwner { require(_proxyAddress != address(0)); + require(USDTieredSTOProxyAddress == address(0)); USDTieredSTOProxyAddress = _proxyAddress; } From 55e47b430e79b5a125438182b2b97a3557e0f691 Mon Sep 17 00:00:00 2001 From: satyam Date: Sat, 22 Sep 2018 14:17:03 +0530 Subject: [PATCH 10/18] typo fix --- contracts/libraries/VersionUtils.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index c7bca2ff2..87c19fd44 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -7,7 +7,7 @@ pragma solidity ^0.4.24; library VersionUtils { /** - * @notice This function use to validate the inputted version + * @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 From 38f919b319bf78df2f7ed7887ea167cee873a93b Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 26 Sep 2018 12:45:31 +0530 Subject: [PATCH 11/18] test cases improvement related to upgradeable MR --- contracts/ModuleRegistry.sol | 10 +- contracts/SecurityTokenRegistry.sol | 4 +- contracts/interfaces/IModuleFactory.sol | 3 +- contracts/interfaces/IModuleRegistry.sol | 7 +- contracts/interfaces/IUSDTieredSTOProxy.sol | 16 +- contracts/libraries/VersionUtils.sol | 6 +- contracts/mocks/MockFactory.sol | 4 +- contracts/mocks/TestSTOFactory.sol | 4 +- .../ERC20DividendCheckpointFactory.sol | 4 +- .../EtherDividendCheckpointFactory.sol | 4 +- contracts/modules/ModuleFactory.sol | 13 +- .../GeneralPermissionManagerFactory.sol | 4 +- contracts/modules/STO/CappedSTOFactory.sol | 4 +- contracts/modules/STO/DummySTOFactory.sol | 4 +- contracts/modules/STO/PreSaleSTOFactory.sol | 4 +- .../ProxyFactory/USDTieredSTOProxyFactory.sol | 29 +- contracts/modules/STO/USDTieredSTO.sol | 4 +- contracts/modules/STO/USDTieredSTOFactory.sol | 29 +- .../CountTransferManagerFactory.sol | 4 +- .../GeneralTransferManagerFactory.sol | 4 +- .../ManualApprovalTransferManagerFactory.sol | 4 +- .../PercentageTransferManagerFactory.sol | 4 +- migrations/2_deploy_contracts.js | 11 +- test/b_capped_sto.js | 135 ++- test/c_checkpoints.js | 83 +- test/d_count_transfer_manager.js | 119 +-- test/e_erc20_dividends.js | 104 +- test/f_ether_dividends.js | 131 ++- test/g_general_permission_manager.js | 152 ++- test/h_general_transfer_manager.js | 147 ++- test/helpers/encodeCall.js | 17 +- test/i_Issuance.js | 126 +-- test/j_manual_approval_transfer_manager.js | 111 +-- test/k_module_registry.js | 894 +++++++++--------- test/l_percentage_transfer_manager.js | 111 ++- test/m_presale_sto.js | 105 +- test/n_security_token_registry.js | 96 +- test/o_security_token.js | 181 ++-- test/p_usd_tiered_sto.js | 120 +-- test/q_usd_tiered_sto_sim.js | 101 +- test/r_concurrent_STO.js | 150 ++- test/s_v130_to_v140_upgrade.js | 89 +- test/t_security_token_registry_proxy.js | 61 +- 43 files changed, 1477 insertions(+), 1736 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 05276f9c4..f6f4cd9fe 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -137,7 +137,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint8 moduleType = moduleFactory.getType(); require(moduleType != 0, "Factory moduleType should not equal to 0"); set(Encoder.getKey('registry', _moduleFactory), uint256(moduleType)); - set(Encoder.getKey('moduleListIndex', _moduleFactory), getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length); + set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length)); pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); emit ModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); @@ -260,7 +260,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint256 counter = 0; for (uint256 i = 0; i < _len; i++) { if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { - if (IOwner(_addressList[i]).owner() == IOwner(_securityToken).owner()) + if (IOwner(_addressList[i]).owner() == IOwner(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[i]))) counter++; } else if (getBool(Encoder.getKey('verified', _addressList[i]))) { @@ -269,17 +269,19 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } address[] memory _tempArray = new address[](counter); counter = 0; - for (uint256 j = 0; j < _tempArray.length; j++) { + for (uint256 j = 0; j < _len; j++) { if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { - if (IOwner(_addressList[j]).owner() == IOwner(_securityToken).owner()) + if (IOwner(_addressList[j]).owner() == IOwner(_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; } /** diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index a572f6e98..c11684d18 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -115,7 +115,7 @@ 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); @@ -356,7 +356,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker should not be expired"); // No need to update the _name - this is the token name, not the ticker name - 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"); diff --git a/contracts/interfaces/IModuleFactory.sol b/contracts/interfaces/IModuleFactory.sol index 08c1a6276..38f2a9e0d 100644 --- a/contracts/interfaces/IModuleFactory.sol +++ b/contracts/interfaces/IModuleFactory.sol @@ -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); @@ -78,7 +79,7 @@ interface IModuleFactory { * @param _boundType Type of bound * @param _newVersion new version array */ - function changeSTVersionBounds(bytes32 _boundType, uint8[] _newVersion) external; + function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external; /** * @notice Get the setup cost of the module diff --git a/contracts/interfaces/IModuleRegistry.sol b/contracts/interfaces/IModuleRegistry.sol index 3b8367dda..ffeba273b 100644 --- a/contracts/interfaces/IModuleRegistry.sol +++ b/contracts/interfaces/IModuleRegistry.sol @@ -67,7 +67,7 @@ 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 @@ -75,4 +75,9 @@ interface IModuleRegistry { */ 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/IUSDTieredSTOProxy.sol b/contracts/interfaces/IUSDTieredSTOProxy.sol index c73d811e3..1f0526d5d 100644 --- a/contracts/interfaces/IUSDTieredSTOProxy.sol +++ b/contracts/interfaces/IUSDTieredSTOProxy.sol @@ -6,10 +6,14 @@ pragma solidity ^0.4.24; interface IUSDTieredSTOProxy { /** - * @notice deploys the STO. + * @notice deploys the STO. + * @param _securityToken Contract address of the securityToken + * @param _polyAddress Contract address of the PolyToken. + * @param _factoryAddress Contract address of the factory + * @return address Address of the deployed STO */ - function deploySTO(address _securityToken, address _polyAddress) external returns (address); - + 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 @@ -17,10 +21,4 @@ interface IUSDTieredSTOProxy { */ function getInitFunction(address _contractAddress) external returns (bytes4); - /** - * @notice Use to intialize the state variables of the STO contract - * @param _contractAddress Address of the STO contract - * @param _data Data that use to intialize the values - */ - function initialize(address _contractAddress, bytes _data) external returns (bool); } \ No newline at end of file diff --git a/contracts/libraries/VersionUtils.sol b/contracts/libraries/VersionUtils.sol index 87c19fd44..9b5f4fcc4 100644 --- a/contracts/libraries/VersionUtils.sol +++ b/contracts/libraries/VersionUtils.sol @@ -13,7 +13,6 @@ library VersionUtils { * @return bool */ function isValidVersion(uint8[] _current, uint8[] _new) internal pure returns(bool) { - require(_current.length == _new.length); bool[] memory _temp = new bool[](_current.length); uint8 counter = 0; for (uint8 i = 0; i < _current.length; i++) { @@ -56,7 +55,7 @@ library VersionUtils { require(_version1.length == _version2.length); uint counter = 0; for (uint8 j = 0; j< _version1.length; j++) { - if (_version1[i] == 0) + if (_version1[j] == 0) counter ++; } if (counter != _version1.length) { @@ -87,7 +86,7 @@ library VersionUtils { require(_version1.length == _version2.length); uint counter = 0; for (uint8 j = 0; j< _version1.length; j++) { - if (_version1[i] == 0) + if (_version1[j] == 0) counter ++; } if (counter != _version1.length) { @@ -128,6 +127,7 @@ library VersionUtils { _unpackVersion[0] = uint8(_packedVersion >> 16); _unpackVersion[1] = uint8(_packedVersion >> 8); _unpackVersion[2] = uint8(_packedVersion); + return _unpackVersion; } diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 375dd562c..2f7772d77 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -17,8 +17,8 @@ contract MockFactory is ModuleFactory { name = "Mock"; title = "Mock Manager"; description = "MockManager"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index eb1da394b..71521e242 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -17,8 +17,8 @@ contract TestSTOFactory is ModuleFactory { name = "TestSTO"; title = "Test STO"; description = "Test STO"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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 e728fe024..d789ad5e3 100644 --- a/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/ERC20DividendCheckpointFactory.sol @@ -22,8 +22,8 @@ contract ERC20DividendCheckpointFactory is ModuleFactory { name = "ERC20DividendCheckpoint"; title = "ERC20 Dividend Checkpoint"; description = "Create ERC20 dividends for token holders at a specific checkpoint"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/EtherDividendCheckpointFactory.sol b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol index 079c28ff4..146691d82 100644 --- a/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol +++ b/contracts/modules/Checkpoint/EtherDividendCheckpointFactory.sol @@ -22,8 +22,8 @@ contract EtherDividendCheckpointFactory is ModuleFactory { name = "EtherDividendCheckpoint"; title = "Ether Dividend Checkpoint"; description = "Create ETH dividends for token holders at a specific checkpoint"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/ModuleFactory.sol b/contracts/modules/ModuleFactory.sol index af09f1357..66ffc822d 100644 --- a/contracts/modules/ModuleFactory.sol +++ b/contracts/modules/ModuleFactory.sol @@ -25,13 +25,13 @@ contract ModuleFactory is IModuleFactory, Ownable { // 2. upperBound // @dev (0.0.0 will act as the wildcard) // @dev uint24 consists packed value of uint8 _major, uint8 _minor, uint8 _patch - mapping(bytes32 => uint24) compatibleSTVersionRange; + 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(bytes32 _boundType, uint8 _major, uint8 _minor, uint8 _patch); + event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch); /** * @notice Constructor @@ -113,8 +113,9 @@ contract ModuleFactory is IModuleFactory, Ownable { * @param _boundType Type of bound * @param _newVersion new version array */ - function changeSTVersionBounds(bytes32 _boundType, uint8[] _newVersion) external onlyOwner { - require(_boundType == bytes32("lowerBound") || _boundType == bytes32("upperBound")); + 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]); @@ -129,7 +130,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @return lower bound */ function getLowerSTVersionBounds() external view returns(uint8[]) { - return VersionUtils.unpack(compatibleSTVersionRange[bytes32("lowerBound")]); + return VersionUtils.unpack(compatibleSTVersionRange["lowerBound"]); } /** @@ -137,7 +138,7 @@ contract ModuleFactory is IModuleFactory, Ownable { * @return upper bound */ function getUpperSTVersionBounds() external view returns(uint8[]) { - return VersionUtils.unpack(compatibleSTVersionRange[bytes32("upperBound")]); + return VersionUtils.unpack(compatibleSTVersionRange["upperBound"]); } } diff --git a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol index bbd35c0f3..e6e6e65a1 100644 --- a/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol +++ b/contracts/modules/PermissionManager/GeneralPermissionManagerFactory.sol @@ -19,8 +19,8 @@ contract GeneralPermissionManagerFactory is ModuleFactory { name = "GeneralPermissionManager"; title = "General Permission Manager"; description = "Manage permissions within the Security Token and attached modules"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/STO/CappedSTOFactory.sol b/contracts/modules/STO/CappedSTOFactory.sol index 7b54f009a..982f790f0 100644 --- a/contracts/modules/STO/CappedSTOFactory.sol +++ b/contracts/modules/STO/CappedSTOFactory.sol @@ -20,8 +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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/STO/DummySTOFactory.sol b/contracts/modules/STO/DummySTOFactory.sol index c7f8a465b..ec249b420 100644 --- a/contracts/modules/STO/DummySTOFactory.sol +++ b/contracts/modules/STO/DummySTOFactory.sol @@ -20,8 +20,8 @@ contract DummySTOFactory is ModuleFactory { name = "DummySTO"; title = "Dummy STO"; description = "Dummy STO"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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 diff --git a/contracts/modules/STO/PreSaleSTOFactory.sol b/contracts/modules/STO/PreSaleSTOFactory.sol index 87f2816b4..03ca13bbe 100644 --- a/contracts/modules/STO/PreSaleSTOFactory.sol +++ b/contracts/modules/STO/PreSaleSTOFactory.sol @@ -20,8 +20,8 @@ contract PreSaleSTOFactory is ModuleFactory { name = "PreSaleSTO"; title = "PreSale STO"; description = "Allows Issuer to configure pre-sale token allocations"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/STO/ProxyFactory/USDTieredSTOProxyFactory.sol b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol index e08d99dd3..dc4d6c628 100644 --- a/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol +++ b/contracts/modules/STO/ProxyFactory/USDTieredSTOProxyFactory.sol @@ -1,14 +1,25 @@ pragma solidity ^0.4.24; import "../USDTieredSTO.sol"; +import "../../../interfaces/IUSDTieredSTOProxy.sol"; -contract USDTieredSTOProxyFactory { +contract USDTieredSTOProxyFactory is IUSDTieredSTOProxy { + + + constructor() public { + + } + /** - * @notice deploys the STO. + * @notice deploys the STO. + * @param _securityToken Contract address of the securityToken + * @param _polyAddress Contract address of the PolyToken. + * @param _factoryAddress Contract address of the factory + * @return address Address of the deployed STO */ - function deploySTO(address _securityToken, address _polyAddress) external returns (address) { - address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _polyAddress); + function deploySTO(address _securityToken, address _polyAddress, address _factoryAddress) external returns (address) { + address newSecurityTokenAddress = new USDTieredSTO(_securityToken, _polyAddress, _factoryAddress); return newSecurityTokenAddress; } @@ -20,14 +31,4 @@ contract USDTieredSTOProxyFactory { function getInitFunction(address _contractAddress) external returns (bytes4) { return USDTieredSTO(_contractAddress).getInitFunction(); } - - /** - * @notice Use to intialize the state variables of the STO contract - * @param _contractAddress Address of the STO contract - * @param _data Data that use to intialize the values - */ - function initialize(address _contractAddress, bytes _data) external returns (bool) { - return USDTieredSTO(_contractAddress).call(_data); - } - } \ 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 b536eb4dd..1b01cec66 100644 --- a/contracts/modules/STO/USDTieredSTOFactory.sol +++ b/contracts/modules/STO/USDTieredSTOFactory.sol @@ -15,15 +15,17 @@ contract USDTieredSTOFactory is ModuleFactory { * @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[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -33,14 +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)); + require(USDTieredSTOProxyAddress != address(0), "Proxy contract should be pre-set"); //Check valid bytes - can only call module init function - address usdTieredSTO = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, address(polyToken)); + address usdTieredSTO = IUSDTieredSTOProxy(USDTieredSTOProxyAddress).deploySTO(msg.sender, address(polyToken), address(this)); //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == IUSDTieredSTOProxy(USDTieredSTOProxyAddress).getInitFunction(usdTieredSTO), "Invalid data"); - require(IUSDTieredSTOProxy(USDTieredSTOProxyAddress).initialize(usdTieredSTO, _data), "Unsuccessfull call"); - emit GenerateModuleFromFactory(address(usdTieredSTO), getName(), address(this), msg.sender, setupCost, now); + require(address(usdTieredSTO).call(_data), "Unsuccessfull call"); + emit GenerateModuleFromFactory(usdTieredSTO, getName(), address(this), msg.sender, setupCost, now); return address(usdTieredSTO); + // return 0xca35b7d915458ef540ade6068dfe2f44e8fa733c; } /** @@ -104,14 +107,4 @@ contract USDTieredSTOFactory is ModuleFactory { return availableTags; } - /** - * @notice Function use to set the proxy address - * @param _proxyAddress Address of the proxy factory contract - */ - function setProxyFactoryAddress(address _proxyAddress) public onlyOwner { - require(_proxyAddress != address(0)); - require(USDTieredSTOProxyAddress == address(0)); - USDTieredSTOProxyAddress = _proxyAddress; - } - } diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index e7849849b..aa7d2cda2 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -20,8 +20,8 @@ contract CountTransferManagerFactory is ModuleFactory { name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/TransferManager/GeneralTransferManagerFactory.sol b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol index a896de646..a3490130b 100644 --- a/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/GeneralTransferManagerFactory.sol @@ -19,8 +19,8 @@ contract GeneralTransferManagerFactory is ModuleFactory { name = "GeneralTransferManager"; title = "General Transfer Manager"; description = "Manage transfers using a time based whitelist"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/TransferManager/ManualApprovalTransferManagerFactory.sol b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol index 0ef126f89..2c0e60eb5 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManagerFactory.sol @@ -22,8 +22,8 @@ contract ManualApprovalTransferManagerFactory is ModuleFactory { name = "ManualApprovalTransferManager"; title = "Manual Approval Transfer Manager"; description = "Manage transfers using single approvals / blocking"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + 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/TransferManager/PercentageTransferManagerFactory.sol b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol index 85319641b..59949880c 100644 --- a/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/PercentageTransferManagerFactory.sol @@ -20,8 +20,8 @@ contract PercentageTransferManagerFactory is ModuleFactory { name = "PercentageTransferManager"; title = "Percentage Transfer Manager"; description = "Restrict the number of investors"; - compatibleSTVersionRange[bytes32("lowerBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange[bytes32("upperBound")] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index 38592883b..f21608730 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -112,7 +112,6 @@ const functionSignatureProxyMR = { ] }; - // POLYMATH NETWORK Configuration :: DO THIS ONLY ONCE // A) Deploy the PolymathRegistry contract return deployer.deploy(PolymathRegistry, {from: PolymathAccount}).then(() => { @@ -125,7 +124,7 @@ const functionSignatureProxyMR = { }).then(() => { return deployer.deploy(ModuleRegistryProxy, {from: PolymathAccount}); }).then(() => { - let bytesProxyMR = web3.eth.abi.encodeFunctionCall(functionSignatureProxyMR, [PolymathRegistry.address, PolymathAccount]); + 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); @@ -262,10 +261,7 @@ const functionSignatureProxyMR = { 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}) - }).then(() => { - // Set proxy factory address into the USDTieredSTOFactory contract - return USDTieredSTOFactory.at(USDTieredSTOFactory.address).setProxyFactoryAddress(USDTieredSTOProxyFactory.address, {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. @@ -287,7 +283,7 @@ const functionSignatureProxyMR = { SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} SecurityTokenRegistry: ${SecurityTokenRegistry.address} ModuleRegistry: ${ModuleRegistry.address} - ModuleRegistryProxy: ${moduleRegistry.address} + ModuleRegistryProxy: ${ModuleRegistryProxy.address} FeatureRegistry: ${FeatureRegistry.address} ETHOracle: ${ETHOracle} @@ -299,6 +295,7 @@ const functionSignatureProxyMR = { CappedSTOFactory: ${CappedSTOFactory.address} USDTieredSTOFactory: ${USDTieredSTOFactory.address} + USDTieredSTOProxyFactory: ${USDTieredSTOProxyFactory.address} CountTransferManagerFactory: ${CountTransferManagerFactory.address} PercentageTransferManagerFactory: ${PercentageTransferManagerFactory.address} 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 47e3334c6..89e25e841 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", - ); + 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 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 93aeb8a8f..c9f904ffd 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 da6a91f56..6a48f12a1 100644 --- a/test/helpers/encodeCall.js +++ b/test/helpers/encodeCall.js @@ -1,15 +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 encodeMRProxyCall(values) { - const parameters = ['address', 'address']; - const methodId = abi.methodID("initialize", parameters).toString('hex'); - const params = abi.rawEncode(parameters, values).toString('hex'); + +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 b8e1a123a..e72c088af 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.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, encodeMRProxyCall } 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'); @@ -20,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'); @@ -65,12 +66,14 @@ contract('ModuleRegistry', accounts => { 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; @@ -90,34 +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 @@ -138,7 +119,6 @@ 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 FeatureRegistry @@ -148,18 +128,21 @@ contract('ModuleRegistry', accounts => { from: account_polymath }); - await I_PolymathRegistry.changeAddress("FeatureRegistry", I_FeatureRegistry.address, {from: account_polymath}); - - // STEP 2: Deploy the ModuleRegistry + // STEP 3: Deploy the ModuleRegistry - I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); - I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from:account_polymath}); + I_ModuleRegistry = await ModuleRegistry.new({from:account_polymath}); + + assert.notEqual( + I_ModuleRegistry.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "ModuleRegistry contract was not deployed", + ); - let bytesMRProxy = encodeMRProxyCall([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); + 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); - await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, {from: account_polymath}); // STEP 2: Deploy the GeneralTransferManagerFactory @@ -191,7 +174,7 @@ 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); @@ -204,6 +187,9 @@ contract('ModuleRegistry', 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("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}); @@ -219,472 +205,453 @@ contract('ModuleRegistry', accounts => { 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_MRProxied.getAddressValues.call(web3.utils.soliditySha3("owner")); - assert.equal(_owner, account_polymath, "Unauthenticated user deployed the contract"); - }); - - it("Should successfully deployed the Module Fatories", 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" - ); - - - 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_MRProxied.pause({ from: account_polymath}); - await I_MRProxied.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_MRProxied.unpause({ from: account_polymath}); - let tx = await I_MRProxied.registerModule(I_GeneralTransferManagerFactory.address, { from: account_polymath }); + describe("Test cases for the ModuleRegistry", async() => { - assert.equal( - tx.logs[0].args._moduleFactory, - I_GeneralTransferManagerFactory.address, - "GeneralTransferManagerFactory is not registerd successfully" - ); + describe("Test case for the upgradeFromregistry", async() => { - assert.equal(tx.logs[0].args._owner, account_polymath); - - tx = await I_MRProxied.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_MRProxied.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_MRProxied.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_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }); - } catch(error) { - console.log(` tx revert -> Module factory of 0 type`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - }); - }); - - describe("Test 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" - ); - }); - - 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_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" - ); - - 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_SecurityTokenRegistryProxy.address, {from: account_polymath}); - - await I_MRProxied.updateFromRegistry({from: account_polymath}); - }); - - }); + 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_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); - }); + 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_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"); }); - 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); - }); + describe("Test the state variables", async() => { - 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, ''),""); - }); + 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}); + 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); + }) + + it("Should failed in adding the TestSTOFactory module because not compatible with the current protocol version --upper", async() => { + await I_TestSTOFactory.changeSTVersionBounds("upperBound", [1,0,0], {from: account_polymath}); + let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() + assert.equal(_ustVersion[0],1); + assert.equal(_ustVersion[1],0); + 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); + describe("Test cases for the tag functions", async() => { - let tx = await I_ModuleRegistry.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"); + 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); + describe("Test case for the getAvailableModulesOfType()", async() => { - assert.equal(sto1,I_CappedSTOFactory1.address); - assert.equal(sto2,I_CappedSTOFactory2.address); - assert.equal((await I_ModuleRegistry.getModuleListOfType.call(3)).length, 2); + 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); + }) - let tx = await I_ModuleRegistry.removeModule(sto2, { from: token_owner }); + 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); + }) + }) - 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"); + describe("Test cases for removeModule()", async() => { - 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); - }); - - 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()); }); @@ -696,7 +663,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; @@ -706,15 +673,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; @@ -724,13 +691,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 38e28315e..dc4f381d8 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 () => { @@ -619,7 +615,7 @@ contract('SecurityTokenRegistry', accounts => { I_SecurityToken002 = SecurityToken.at(tx.logs[1].args._securityTokenAddress); - 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 ce24a9be0..fea3e3687 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} @@ -288,7 +262,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); @@ -307,49 +281,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(); @@ -511,7 +442,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 }); @@ -526,7 +457,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; @@ -543,7 +474,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 d60b45d2d..578ea1b75 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} @@ -300,7 +310,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", @@ -311,9 +322,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); }); @@ -334,16 +345,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); }); @@ -362,9 +373,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); }); @@ -499,36 +510,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); From 16373dcc074c9b4ee3ab72978dc2affa91d92236 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 26 Sep 2018 14:35:21 +0530 Subject: [PATCH 12/18] add test cases for the module registry proxy --- contracts/mocks/ModuleRegistryMock.sol | 18 ++ test/u_module_registry_proxy.js | 347 +++++++++++++++++++++++++ 2 files changed, 365 insertions(+) create mode 100644 contracts/mocks/ModuleRegistryMock.sol create mode 100644 test/u_module_registry_proxy.js 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/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js new file mode 100644 index 000000000..3a251c9cb --- /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); + }); + }) + + +}) From f157b8559f9bf4079441d6b50ae77ac7a6ad7804 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 26 Sep 2018 14:57:27 +0530 Subject: [PATCH 13/18] minor fix --- test/u_module_registry_proxy.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 3a251c9cb..82583d594 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -4,7 +4,7 @@ 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 GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); const ModuleRegistryMock = artifacts.require("./ModuleRegistryMock.sol"); const OwnedUpgradeabilityProxy = artifacts.require('./OwnedUpgradeabilityProxy.sol'); const PolymathRegistry = artifacts.require('./PolymathRegistry.sol') @@ -181,12 +181,12 @@ contract ("ModuleRegistryProxy", accounts => { it("Register and verify the new module", async() => { - I_GeneralPermissionManagerfactory = await GeneralPermissionManagerfactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); + 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" + "GeneralPermissionManagerFactory contract was not deployed" ); await I_MRProxied.registerModule(I_GeneralPermissionManagerfactory.address, { from: account_polymath }); From 38edf14791cddfad3b5c09a45f0a92509230b17a Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 26 Sep 2018 15:50:55 +0530 Subject: [PATCH 14/18] remove old mr contract to increase the coverage --- contracts/OldModuleRegistry.sol | 200 -------------------------------- 1 file changed, 200 deletions(-) delete mode 100644 contracts/OldModuleRegistry.sol diff --git a/contracts/OldModuleRegistry.sol b/contracts/OldModuleRegistry.sol deleted file mode 100644 index aa075e976..000000000 --- a/contracts/OldModuleRegistry.sol +++ /dev/null @@ -1,200 +0,0 @@ -pragma solidity ^0.4.24; - -import "./interfaces/IModuleRegistry.sol"; -import "./interfaces/IModuleFactory.sol"; -import "./interfaces/ISecurityTokenRegistry.sol"; -import "./interfaces/IFeatureRegistry.sol"; -import "./Pausable.sol"; -import "./RegistryUpdater.sol"; -import "./ReclaimTokens.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 -*/ -contract OldModuleRegistry 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) - { - } - - /** - * @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 - * @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"); - } else { - require(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); - } - } - - /** - * @notice Called by moduleFactory owner to register new modules for SecurityToken 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"); - 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; - } - - /** - * @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 - */ - function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { - uint8 moduleType = 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"); - - uint8 index = moduleListIndex[_moduleFactory]; - uint8 last = uint8(moduleList[moduleType].length - 1); - address temp = moduleList[moduleType][last]; - - // pop from array and re-order - if (index != last) { - moduleList[moduleType][index] = temp; - moduleListIndex[temp] = index; - } - delete moduleList[moduleType][last]; - moduleList[moduleType].length--; - - delete registry[_moduleFactory]; - delete reputation[_moduleFactory]; - delete verified[_moduleFactory]; - delete moduleListIndex[_moduleFactory]; - - emit LogModuleRemoved (_moduleFactory, msg.sender); - return true; - } - - /** - * @notice Called by Polymath to verify modules for SecurityToken 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 - * @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); - return true; - } - - /** - * @notice Add the tag for specified Module Factory - * @param _moduleType Type of module. - * @param _tag List of tags - */ - function addTagByModuleType(uint8 _moduleType, bytes32[] _tag) external onlyOwner { - for (uint8 i = 0; i < _tag.length; i++) { - availableTags[_moduleType].push(_tag[i]); - } - } - - /** - * @notice remove the tag for specified Module Factory - * @param _moduleType Type of module. - * @param _removedTags List of tags - */ - function removeTagByModuleType(uint8 _moduleType, bytes32[] _removedTags) external onlyOwner { - for (uint8 i = 0; i < availableTags[_moduleType].length; i++) { - for (uint8 j = 0; j < _removedTags.length; j++) { - if (availableTags[_moduleType][i] == _removedTags[j]) { - delete availableTags[_moduleType][i]; - } - } - } - } - - /** - * @notice Use to get all the tags releated to the functionality of the Module Factory. - * @param _moduleType Type of module - * @return bytes32 array - */ - function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]) { - return availableTags[_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 - */ - function getReputationOfFactory(address _factoryAddress) external view returns(address[]) { - return reputation[_factoryAddress]; - } - - /** - * @notice Use to get the list of addresses of Module factory for a particular type - * @param _moduleType Type of Module - * @return address array thal contains the lis of addresses of module factory contracts. - */ - function getModuleListOfType(uint8 _moduleType) external view returns(address[]) { - return moduleList[_moduleType]; - } - - /** - * @notice pause registration function - */ - function unpause() public onlyOwner { - _unpause(); - } - - /** - * @notice unpause registration function - */ - function pause() public onlyOwner { - _pause(); - } - - -} From a3b7d25afba8be5388264c246f4e7ee4f3954c8e Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Wed, 26 Sep 2018 12:18:34 -0300 Subject: [PATCH 15/18] comments cleanup --- contracts/ModuleRegistry.sol | 67 ++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index f6f4cd9fe..76efded02 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -13,7 +13,7 @@ import "./interfaces/IOwner.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, EternalStorage { /* @@ -23,16 +23,16 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // 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 containing the list of addresses of Module Factories of a particular type mapping (uint8 => address[]) public moduleList; - // Mapping to store the index of the moduleFactory in the 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 corresponds to the module type + // Contains the list of the available tags corresponding to each module type mapping (uint8 => bytes32[]) public availableTags; */ @@ -40,17 +40,17 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // Events ////////// - // Emit when ecosystem get paused + // Emit when network becomes paused event Pause(uint256 _timestammp); - // Emit when ecosystem get unpaused + // Emit when network becomes unpaused event Unpause(uint256 _timestamp); - // Emit when Module been used by the securityToken + // Emit when Module is used by the SecurityToken event ModuleUsed(address indexed _moduleFactory, address indexed _securityToken); - // Emit when the Module Factory get registered with the ModuleRegistry contract + // Emit when the Module Factory gets registered on the ModuleRegistry contract event ModuleRegistered(address indexed _moduleFactory, address indexed _owner); - // Emit when the module get verified by the Polymath team + // Emit when the module gets verified by Polymath event ModuleVerified(address indexed _moduleFactory, bool _verified); - // Emit when a moduleFactory is removed by Polymath or moduleFactory owner + // Emit when a ModuleFactory is removed by Polymath event ModuleRemoved(address indexed _moduleFactory, address indexed _decisionMaker); /////////////// @@ -100,8 +100,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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 @@ -127,7 +127,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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 */ @@ -145,8 +145,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice Called by moduleFactory owner or registry curator to delete a moduleFactory - * @param _moduleFactory is the address of the module factory to be deleted + * @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 * @return bool */ function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { @@ -181,10 +181,11 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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) { @@ -196,9 +197,9 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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 + * @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++) { @@ -207,9 +208,9 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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 + * @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 < getArrayBytes32(Encoder.getKey('availableTags', uint256(_moduleType))).length; i++) { @@ -222,8 +223,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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[]) { @@ -231,16 +232,16 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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 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 that contains the list of addresses of module factory contracts. */ @@ -249,9 +250,9 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @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 + * @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 getAvailableModulesOfType(uint8 _moduleType, address _securityToken) external view returns (address[]) { @@ -312,7 +313,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice Use to get the latest contract address of the regstries + * @notice Used to get the latest contract address of the registries */ function updateFromRegistry() onlyOwner external { address _polymathRegistry = getAddress(Encoder.getKey('polymathRegistry')); From 5d76ff8bbfd9d6a92a40be5346dfa8e2d8fd55c3 Mon Sep 17 00:00:00 2001 From: satyam Date: Wed, 26 Sep 2018 22:06:07 +0530 Subject: [PATCH 16/18] add IOwnable in mr --- contracts/ModuleRegistry.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index f6f4cd9fe..fce11554b 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -9,7 +9,7 @@ import "./interfaces/IERC20.sol"; import "./libraries/VersionUtils.sol"; import "./storage/EternalStorage.sol"; import "./libraries/Encoder.sol"; -import "./interfaces/IOwner.sol"; +import "./interfaces/IOwnable.sol"; /** * @title Registry contract to store registered modules @@ -110,7 +110,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // This if statement is required to be able to add modules from the token proxy contract during deployment if (ISecurityTokenRegistry(getAddress(Encoder.getKey('securityTokenRegistry'))).isSecurityToken(msg.sender)) { if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { - require(getBool(Encoder.getKey('verified', _moduleFactory)) || IOwner(_moduleFactory).owner() == IOwner(msg.sender).owner(), + require(getBool(Encoder.getKey('verified', _moduleFactory)) || IOwnable(_moduleFactory).owner() == IOwnable(msg.sender).owner(), "ModuleFactory must be verified or SecurityToken owner must be ModuleFactory owner"); } else { require(getBool(Encoder.getKey('verified', _moduleFactory)), "ModuleFactory must be verified"); @@ -140,7 +140,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(getArrayAddress(Encoder.getKey('moduleList', uint256(moduleType))).length)); pushArray(Encoder.getKey('moduleList', uint256(moduleType)), _moduleFactory); setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); - emit ModuleRegistered (_moduleFactory, IOwner(_moduleFactory).owner()); + emit ModuleRegistered (_moduleFactory, IOwnable(_moduleFactory).owner()); return true; } @@ -153,7 +153,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint256 moduleType = getUint(Encoder.getKey('registry', _moduleFactory)); require(moduleType != 0, "Module factory should be registered"); - require(msg.sender == IOwner(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), + require(msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), "msg.sender must be moduleFactory owner or registry curator"); uint256 index = getUint(Encoder.getKey('moduleListIndex', _moduleFactory)); @@ -260,7 +260,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint256 counter = 0; for (uint256 i = 0; i < _len; i++) { if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { - if (IOwner(_addressList[i]).owner() == IOwner(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[i]))) + if (IOwnable(_addressList[i]).owner() == IOwnable(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[i]))) counter++; } else if (getBool(Encoder.getKey('verified', _addressList[i]))) { @@ -271,7 +271,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { counter = 0; for (uint256 j = 0; j < _len; j++) { if (IFeatureRegistry(getAddress(Encoder.getKey('featureRegistry'))).getFeatureStatus("customModulesAllowed")) { - if (IOwner(_addressList[j]).owner() == IOwner(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[j]))) { + if (IOwnable(_addressList[j]).owner() == IOwnable(_securityToken).owner() || getBool(Encoder.getKey('verified', _addressList[j]))) { _tempArray[counter] = _addressList[j]; counter ++; } From fb701344f1eaea954f98c583aab22c19c73b5ea4 Mon Sep 17 00:00:00 2001 From: Pablo Ruiz Date: Wed, 26 Sep 2018 15:41:27 -0300 Subject: [PATCH 17/18] more comments fixing --- contracts/ModuleRegistry.sol | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 6e826fcd1..07d25f50f 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -118,8 +118,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { uint8[] memory _latestVersion = ISecurityTokenRegistry(getAddress(Encoder.getKey('securityTokenRegistry'))).getProtocolVersion(); uint8[] memory _lowerBound = IModuleFactory(_moduleFactory).getLowerSTVersionBounds(); uint8[] memory _upperBound = IModuleFactory(_moduleFactory).getUpperSTVersionBounds(); - require(VersionUtils.compareLowerBound(_lowerBound, _latestVersion), "Should not below the lower bound of ST"); - require(VersionUtils.compareUpperBound(_upperBound, _latestVersion), "Should not above the upper bound of ST"); + 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); @@ -154,7 +154,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { require(moduleType != 0, "Module factory should be registered"); require(msg.sender == IOwnable(_moduleFactory).owner() || msg.sender == getAddress(Encoder.getKey('owner')), - "msg.sender must be moduleFactory owner or registry curator"); + "msg.sender must be the Module Factory owner or registry curator"); uint256 index = getUint(Encoder.getKey('moduleListIndex', _moduleFactory)); uint256 last = getArrayAddress(Encoder.getKey('moduleList', moduleType)).length - 1; @@ -176,7 +176,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { set(Encoder.getKey('verified', _moduleFactory), false); // delete moduleListIndex[_moduleFactory]; set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(0)); - emit ModuleRemoved (_moduleFactory, msg.sender); + emit ModuleRemoved(_moduleFactory, msg.sender); return true; } @@ -189,8 +189,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { * @return bool */ function verifyModule(address _moduleFactory, bool _verified) external onlyOwner returns(bool) { - //Must already have been registered - require(getUint(Encoder.getKey('registry', _moduleFactory)) != uint256(0), "Module factory should have been already registered"); + 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; @@ -297,7 +296,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice called by the owner to pause, triggers stopped state + * @notice Called by the owner to pause, triggers stopped state */ function pause() external whenNotPaused onlyOwner { set(Encoder.getKey("paused"), true); @@ -305,7 +304,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice called by the owner to unpause, returns to normal state + * @notice Called by the owner to unpause, returns to normal state */ function unpause() external whenPaused onlyOwner { set(Encoder.getKey("paused"), false); @@ -313,7 +312,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } /** - * @notice Used to get the latest contract address of the registries + * @notice Stores the contract addresses of other key contracts from the PolymathRegistry */ function updateFromRegistry() onlyOwner external { address _polymathRegistry = getAddress(Encoder.getKey('polymathRegistry')); From 5cbafb32adf0dd904fa04c1c3f9e6c13db91cae7 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 27 Sep 2018 14:39:44 +0530 Subject: [PATCH 18/18] add setters for index value and add the getVersion() in ST --- contracts/ModuleRegistry.sol | 16 +++++++--------- contracts/SecurityTokenRegistry.sol | 2 +- contracts/interfaces/IModuleRegistry.sol | 5 ++--- contracts/interfaces/ISecurityToken.sol | 5 +++++ contracts/storage/EternalStorage.sol | 23 +++++++++++++++++++++++ contracts/tokens/SecurityToken.sol | 21 ++++++++++++++++++++- test/k_module_registry.js | 9 ++++++--- 7 files changed, 64 insertions(+), 17 deletions(-) diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index 6e826fcd1..396ef3505 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -10,6 +10,7 @@ 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 @@ -115,7 +116,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { } else { require(getBool(Encoder.getKey('verified', _moduleFactory)), "ModuleFactory must be verified"); } - uint8[] memory _latestVersion = ISecurityTokenRegistry(getAddress(Encoder.getKey('securityTokenRegistry'))).getProtocolVersion(); + uint8[] memory _latestVersion = ISecurityToken(msg.sender).getVersion(); uint8[] memory _lowerBound = IModuleFactory(_moduleFactory).getLowerSTVersionBounds(); uint8[] memory _upperBound = IModuleFactory(_moduleFactory).getUpperSTVersionBounds(); require(VersionUtils.compareLowerBound(_lowerBound, _latestVersion), "Should not below the lower bound of ST"); @@ -129,9 +130,8 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { /** * @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) { + 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(); @@ -139,17 +139,14 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { 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); - setArray(Encoder.getKey('reputation', _moduleFactory), new address[](0)); emit ModuleRegistered (_moduleFactory, IOwnable(_moduleFactory).owner()); - return true; } /** * @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 - * @return bool */ - function removeModule(address _moduleFactory) external whenNotPaused returns(bool) { + function removeModule(address _moduleFactory) external whenNotPaused { uint256 moduleType = getUint(Encoder.getKey('registry', _moduleFactory)); require(moduleType != 0, "Module factory should be registered"); @@ -163,7 +160,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // pop from array and re-order if (index != last) { // moduleList[moduleType][index] = temp; - addressArrayStorage[Encoder.getKey('moduleList', moduleType)][index] = temp; + setArrayIndexValue(Encoder.getKey('moduleList', moduleType), index, temp); set(Encoder.getKey('moduleListIndex', temp), index); } deleteArrayAddress(Encoder.getKey('moduleList', moduleType), last); @@ -177,7 +174,6 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { // delete moduleListIndex[_moduleFactory]; set(Encoder.getKey('moduleListIndex', _moduleFactory), uint256(0)); emit ModuleRemoved (_moduleFactory, msg.sender); - return true; } /** @@ -198,6 +194,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { /** * @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. */ @@ -209,6 +206,7 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { /** * @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 */ diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index c9270bfef..9a4e66b0b 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -159,7 +159,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("paused"), false); set(Encoder.getKey("owner"), _owner); set(Encoder.getKey("polymathRegistry"), _polymathRegistry); - _setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(1)); + _setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(2)); set(Encoder.getKey("initialised"), true); } diff --git a/contracts/interfaces/IModuleRegistry.sol b/contracts/interfaces/IModuleRegistry.sol index ffeba273b..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. 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/storage/EternalStorage.sol b/contracts/storage/EternalStorage.sol index 1fc4006c8..d476b13bb 100644 --- a/contracts/storage/EternalStorage.sol +++ b/contracts/storage/EternalStorage.sol @@ -208,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 270211462..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; @@ -205,6 +212,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr updateFromRegistry(); tokenDetails = _tokenDetails; granularity = _granularity; + securityTokenVersion = SemanticVersion(0,0,2); } /** @@ -804,4 +812,15 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr 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/test/k_module_registry.js b/test/k_module_registry.js index e72c088af..6843db491 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -463,6 +463,8 @@ contract('ModuleRegistry', accounts => { 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); @@ -477,13 +479,14 @@ contract('ModuleRegistry', accounts => { 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", [1,0,0], {from: account_polymath}); + await I_TestSTOFactory.changeSTVersionBounds("upperBound", [0,0,1], {from: account_polymath}); let _ustVersion = await I_TestSTOFactory.getUpperSTVersionBounds.call() - assert.equal(_ustVersion[0],1); - assert.equal(_ustVersion[1],0); + assert.equal(_ustVersion[0],0); + assert.equal(_ustVersion[2],1); await I_STRProxied.setProtocolVersion(I_STFactory.address, 1, 0, 1); // Generate the new securityToken