Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
) 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 {
return 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