Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/libraries/TokenLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ library TokenLib {
uint8[] moduleTypes;
uint256[] moduleIndexes;
uint256 nameIndex;
bytes32 label;
}

// Structures to maintain checkpoints of balances for governance / dividends
Expand Down
49 changes: 33 additions & 16 deletions contracts/tokens/SecurityToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ contract SecurityToken is ERC20, ERC20Detailed, ReentrancyGuard, RegistryUpdater
address _module,
uint256 _moduleCost,
uint256 _budget,
bytes32 _label,
uint256 _timestamp
);

Expand Down Expand Up @@ -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);
Expand All @@ -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, "");
}

/**
Expand Down Expand Up @@ -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);
}

/**
Expand Down
23 changes: 22 additions & 1 deletion test/o_security_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -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 () => {
Expand Down