diff --git a/contracts/libraries/TokenLib.sol b/contracts/libraries/TokenLib.sol index 42e5bebff..8c823ae29 100644 --- a/contracts/libraries/TokenLib.sol +++ b/contracts/libraries/TokenLib.sol @@ -16,6 +16,7 @@ library TokenLib { uint8[] moduleTypes; uint256[] moduleIndexes; uint256 nameIndex; + bytes32 label; } // Structures to maintain checkpoints of balances for governance / dividends diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 9cb54865c..3c27d7d94 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -90,6 +90,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater address _module, uint256 _moduleCost, uint256 _budget, + bytes32 _label, uint256 _timestamp ); @@ -213,21 +214,24 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater securityTokenVersion = SemanticVersion(2,0,0); } - /** - * @notice Attachs a module to the SecurityToken - * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it - * @dev to control restrictions on transfers. - * @param _moduleFactory is the address of the module factory to be added - * @param _data is data packed into bytes used to further configure the module (See STO usage) - * @param _maxCost max amount of POLY willing to pay to the module. - * @param _budget max amount of ongoing POLY willing to assign to the module. - */ - function addModule( + // /** + // * @notice Attachs a module to the SecurityToken + // * @dev E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it + // * @dev to control restrictions on transfers. + // * @param _moduleFactory is the address of the module factory to be added + // * @param _data is data packed into bytes used to further configure the module (See STO usage) + // * @param _maxCost max amount of POLY willing to pay to the module. + // * @param _budget max amount of ongoing POLY willing to assign to the module. + // * @param _label custom module label. + // */ + + function addModuleWithLabel( address _moduleFactory, bytes _data, uint256 _maxCost, - uint256 _budget - ) external onlyOwner nonReentrant { + uint256 _budget, + bytes32 _label + ) public onlyOwner nonReentrant { //Check that the module factory exists in the ModuleRegistry - will throw otherwise IModuleRegistry(moduleRegistry).useModule(_moduleFactory); IModuleFactory moduleFactory = IModuleFactory(_moduleFactory); @@ -250,12 +254,24 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater modules[moduleTypes[i]].push(module); } modulesToData[module] = TokenLib.ModuleData( - moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length + moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length, _label ); names[moduleName].push(module); //Emit log event /*solium-disable-next-line security/no-block-members*/ - emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, now); + emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, _label, now); + } + + /** + * @notice addModule function will call addModuleWithLabel() with an empty label for backward compatible + */ + function addModule( + address _moduleFactory, + bytes _data, + uint256 _maxCost, + uint256 _budget + ) external { + addModuleWithLabel(_moduleFactory, _data, _maxCost, _budget, ""); } /** @@ -330,12 +346,13 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater * @return bool module archived * @return uint8 module type */ - function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[]) { + function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[], bytes32) { return (modulesToData[_module].name, modulesToData[_module].module, modulesToData[_module].moduleFactory, modulesToData[_module].isArchived, - modulesToData[_module].moduleTypes); + modulesToData[_module].moduleTypes, + modulesToData[_module].label); } /** diff --git a/test/o_security_token.js b/test/o_security_token.js index 9cee77f80..39b026828 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -296,7 +296,27 @@ contract("SecurityToken", accounts => { ); }); + it("Should successfully add module with label", async () => { + let snapId = await takeSnapshot(); + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + + await I_PolyToken.getTokens(cappedSTOSetupCost, token_owner); + await I_PolyToken.transfer(I_SecurityToken.address, cappedSTOSetupCost, { from: token_owner }); + console.log("0"); + const tx = await I_SecurityToken.addModuleWithLabel(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, 'stofactory', { from: token_owner }); + console.log("1"); + assert.equal(tx.logs[3].args._types[0], stoKey, "CappedSTO doesn't get deployed"); + assert.equal(web3.utils.toUtf8(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); + console.log("module label is .. "+ web3.utils.toAscii(tx.logs[3].args._label)); + assert(web3.utils.toAscii(tx.logs[3].args._label), "stofactory", "label doesnt match"); + I_CappedSTO = CappedSTO.at(tx.logs[3].args._module); + await revertToSnapshot(snapId); + }); + it("Should successfully attach the STO factory with the security token", async () => { + startTime = latestTime() + duration.seconds(5000); endTime = startTime + duration.days(30); let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); @@ -327,13 +347,14 @@ contract("SecurityToken", accounts => { }); describe("Module related functions", async () => { - it("Should get the modules of the securityToken by index", async () => { + it(" Should get the modules of the securityToken by name", async () => { let moduleData = await I_SecurityToken.getModule.call(I_CappedSTO.address); assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ""), "CappedSTO"); assert.equal(moduleData[1], I_CappedSTO.address); assert.equal(moduleData[2], I_CappedSTOFactory.address); assert.equal(moduleData[3], false); assert.equal(moduleData[4][0], 3); + assert.equal(moduleData[5], 0x0000000000000000000000000000000000000000); }); it("Should get the modules of the securityToken by index (not added into the security token yet)", async () => {