From 4a8d1190f92b80886d3b78c9cb1f4ab0f31cccd0 Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 15 Oct 2018 12:35:11 +0530 Subject: [PATCH 1/6] branches coverage reached to 85 % --- .solcover.js | 2 +- contracts/ModuleRegistry.sol | 1 - contracts/SecurityTokenRegistry.sol | 1 + contracts/interfaces/ISecurityToken.sol | 7 +- contracts/mocks/MockFactory.sol | 21 +- contracts/tokens/SecurityToken.sol | 19 +- test/b_capped_sto.js | 6 + test/d_count_transfer_manager.js | 74 ++++++ test/g_general_permission_manager.js | 303 ++++++++---------------- test/h_general_transfer_manager.js | 2 +- test/k_module_registry.js | 168 +++++++++++-- test/n_security_token_registry.js | 133 ++++++++++- test/o_security_token.js | 27 ++- test/p_usd_tiered_sto.js | 16 ++ test/v_tracked_redemptions.js | 16 ++ 15 files changed, 552 insertions(+), 244 deletions(-) diff --git a/.solcover.js b/.solcover.js index c7a6ed7d1..a99645f37 100644 --- a/.solcover.js +++ b/.solcover.js @@ -4,6 +4,6 @@ module.exports = { copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` --network coverage', deepSkip: true, - skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles'], + skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol'], forceParse: ['mocks', 'oracles'] }; diff --git a/contracts/ModuleRegistry.sol b/contracts/ModuleRegistry.sol index b7b85c2b5..03c5f3016 100644 --- a/contracts/ModuleRegistry.sol +++ b/contracts/ModuleRegistry.sol @@ -126,7 +126,6 @@ contract ModuleRegistry is IModuleRegistry, EternalStorage { require(getBool(Encoder.getKey("verified", _moduleFactory)), "ModuleFactory must be verified"); } require(_isCompatibleModule(_moduleFactory, msg.sender), "Version should within the compatible range of ST"); - 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); } diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 9286a1a7f..7385314fc 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -669,6 +669,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _patch Patch version of the proxy */ function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { + require(_STFactoryAddress != address(0)); _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); } diff --git a/contracts/interfaces/ISecurityToken.sol b/contracts/interfaces/ISecurityToken.sol index e099006bc..c845cc30d 100644 --- a/contracts/interfaces/ISecurityToken.sol +++ b/contracts/interfaces/ISecurityToken.sol @@ -127,12 +127,13 @@ interface ISecurityToken { */ function investors(uint256 _index) external view returns (address); - /** - * @notice allows the owner to withdraw unspent POLY stored by them on the ST. + /** + * @notice allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee. + * @param _tokenContract Address of the ERC20Basic compliance token * @param _value amount of POLY to withdraw */ - function withdrawPoly(uint256 _value) external; + function withdrawERC20(address _tokenContract, uint256 _value) external; /** * @notice allows owner to approve more POLY to one of the modules diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 144db6b15..d6b1e4390 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -4,8 +4,13 @@ import "../modules/STO/DummySTO.sol"; import "../modules/ModuleFactory.sol"; import "../libraries/Util.sol"; +/** + * @title Mock Contract Not fit for production environment + */ + contract MockFactory is ModuleFactory { + bool public switchTypes = false; /** * @notice Constructor * @param _polyAddress Address of the polytoken @@ -41,8 +46,16 @@ contract MockFactory is ModuleFactory { * @notice Type of the Module factory */ function getTypes() external view returns(uint8[]) { - uint8[] memory res = new uint8[](0); - return res; + if (!switchTypes) { + uint8[] memory types = new uint8[](0); + return types; + } else { + uint8[] memory res = new uint8[](2); + res[0] = 1; + res[1] = 1; + return res; + } + } /** @@ -96,4 +109,8 @@ contract MockFactory is ModuleFactory { return availableTags; } + function changeTypes() external onlyOwner { + switchTypes = !switchTypes; + } + } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index dde865fa8..1d2b165f5 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -341,13 +341,16 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr return modules[_type]; } - /** - * @notice allows the owner to withdraw unspent POLY stored by them on the ST. + /** + * @notice allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token. * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee. + * @param _tokenContract Address of the ERC20Basic compliance token * @param _value amount of POLY to withdraw */ - function withdrawPoly(uint256 _value) external onlyOwner { - require(ERC20(polyToken).transfer(owner, _value), "Insufficient balance"); + function withdrawERC20(address _tokenContract, uint256 _value) external onlyOwner { + require(_tokenContract != address(0)); + IERC20 token = IERC20(_tokenContract); + require(token.transfer(owner, _value)); } /** @@ -429,7 +432,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @notice freezes transfers */ function freezeTransfers() external onlyOwner { - require(!transfersFrozen, "transfers already frozen"); + require(!transfersFrozen, "Already frozen"); transfersFrozen = true; emit FreezeTransfers(true, now); } @@ -438,7 +441,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @notice unfreeze transfers */ function unfreezeTransfers() external onlyOwner { - require(transfersFrozen, "transfer are not fronzen"); + require(transfersFrozen, "Not frozen"); transfersFrozen = false; emit FreezeTransfers(false, now); } @@ -730,7 +733,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @param _controller address of the controller */ function setController(address _controller) public onlyOwner { - require(!controllerDisabled,"Controller functions are disabled"); + require(!controllerDisabled,"Controller disabled"); emit SetController(controller, _controller); controller = _controller; } @@ -740,7 +743,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr * @dev enabled via feature switch "disableControllerAllowed" */ function disableController() external isEnabled("disableControllerAllowed") onlyOwner { - require(!controllerDisabled,"Controller functions are disabled"); + require(!controllerDisabled,"Controller disabled"); controllerDisabled = true; delete controller; emit DisableController(now); diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index 33fc5f6a6..d52931939 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -259,6 +259,12 @@ contract("CappedSTO", accounts => { assert.equal(web3.utils.hexToString(tx.logs[3].args._name), "CappedSTO", "CappedSTOFactory module was not added"); I_CappedSTO_Array_ETH.push(CappedSTO.at(tx.logs[3].args._module)); }); + + it("Should call the configure function -- fail because of the bad owner", async()=> { + await catchRevert( + I_CappedSTO_Array_ETH[0].configure(startTime_ETH1, endTime_ETH1, cap, rate, [E_fundRaiseType], account_fundsReceiver, {from: account_polymath }) + ); + }) }); describe("verify the data of STO", async () => { diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 3bf785a5d..97e09461b 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -349,5 +349,79 @@ contract("CountTransferManager", accounts => { assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Count"); }); }); + + describe("Test cases for the ModuleFactory", async() => { + it("Should successfully change the SetupCost -- fail beacuse of bad owner", async() => { + await catchRevert( + I_CountTransferManagerFactory.changeFactorySetupFee(web3.utils.toWei("500"), {from: account_investor3}) + ); + }); + + it("Should successfully change the setupCost", async() => { + await I_CountTransferManagerFactory.changeFactorySetupFee(web3.utils.toWei("800"), { from: account_polymath }); + assert.equal(await I_CountTransferManagerFactory.getSetupCost.call(), web3.utils.toWei("800")); + }) + + it("Should successfully change the usage fee -- fail beacuse of bad owner", async() => { + await catchRevert( + I_CountTransferManagerFactory.changeFactoryUsageFee(web3.utils.toWei("500"), {from: account_investor3}) + ); + }); + + it("Should successfully change the usage fee", async() => { + await I_CountTransferManagerFactory.changeFactoryUsageFee(web3.utils.toWei("800"), { from: account_polymath }); + assert.equal(await I_CountTransferManagerFactory.usageCost.call(), web3.utils.toWei("800")); + }); + + it("Should successfully change the subscription fee -- fail beacuse of bad owner", async() => { + await catchRevert( + I_CountTransferManagerFactory.changeFactorySubscriptionFee(web3.utils.toWei("500"), {from: account_investor3}) + ); + }); + + it("Should successfully change the subscription fee", async() => { + await I_CountTransferManagerFactory.changeFactorySubscriptionFee(web3.utils.toWei("800"), { from: account_polymath }); + assert.equal(await I_CountTransferManagerFactory.monthlySubscriptionCost.call(), web3.utils.toWei("800")); + }); + + it("Should successfully change the version of the factory -- failed because of bad owner", async() => { + await catchRevert( + I_CountTransferManagerFactory.changeVersion("5.0.0", {from: account_investor3}) + ); + }); + + it("Should successfully change the version of the fatory -- failed because of the 0 string", async() => { + await catchRevert( + I_CountTransferManagerFactory.changeVersion("", {from: account_polymath}) + ); + }); + + it("Should successfully change the version of the fatory", async() => { + await I_CountTransferManagerFactory.changeVersion("5.0.0", {from: account_polymath}); + assert.equal(await I_CountTransferManagerFactory.getVersion.call(), "5.0.0"); + }); + }) + + describe("Test case for the changeSTVersionBounds", async() => { + it("Should successfully change the version bounds -- failed because of the non permitted bound type", async() => { + await catchRevert( + I_CountTransferManagerFactory.changeSTVersionBounds("middleType", [1,2,3], {from: account_polymath}) + ); + }) + + it("Should successfully change the version bound --failed because the new version length < 3", async()=> { + await catchRevert( + I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,2], {from: account_polymath}) + ); + }) + + it("Should successfully change the version bound", async()=> { + await I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,2,1], {from: account_polymath}); + await I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,4,9], {from: account_polymath}); + await catchRevert( + I_CountTransferManagerFactory.changeSTVersionBounds("lowerBound", [1,0,0], {from: account_polymath}) + ); + }) + }) }); }); diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index b04f8a18d..cd8d9c580 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -1,25 +1,14 @@ import latestTime from './helpers/latestTime'; 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, 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'); +import { duration, promisifyLogWatch, latestBlock } from './helpers/utils'; +import { takeSnapshot, increaseTime, revertToSnapshot } from './helpers/time'; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, deployGPMAndVerifyed } from "./helpers/createInstances"; + 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 GeneralPermissionManagerFactory = artifacts.require('./GeneralPermissionManagerFactory.sol'); -const GeneralTransferManagerFactory = artifacts.require('./GeneralTransferManagerFactory.sol'); const GeneralTransferManager = artifacts.require('./GeneralTransferManager'); const GeneralPermissionManager = artifacts.require('./GeneralPermissionManager'); -const PolyTokenFaucet = artifacts.require('./PolyTokenFaucet.sol'); const Web3 = require('web3'); const BigNumber = require('bignumber.js'); @@ -63,7 +52,6 @@ contract('GeneralPermissionManager', accounts => { let I_SecurityToken; let I_MRProxied; let I_STRProxied; - let I_DummySTO; let I_PolyToken; let I_PolymathRegistry; @@ -83,17 +71,6 @@ contract('GeneralPermissionManager', accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); - // Dummy STO details - const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time - 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 = encodeModuleCall(STOParameters, [startTime, endTime, cap, someString]); - before(async() => { // Accounts setup account_polymath = accounts[0]; @@ -109,139 +86,41 @@ contract('GeneralPermissionManager', accounts => { account_delegate3 = accounts[5]; - // ----------- 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 + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); - 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}); - - assert.notEqual( - I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralTransferManagerFactory contract was not deployed" - ); + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; // STEP 5: Deploy the GeneralDelegateManagerFactory - - I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); // STEP 6: Deploy the GeneralDelegateManagerFactory - - P_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, web3.utils.toWei("500","ether"), 0, 0, {from:account_polymath}); - - assert.notEqual( - P_GeneralPermissionManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "GeneralDelegateManagerFactory contract was not deployed" - ); - - // STEP 7: Deploy the DummySTOFactory - - I_DummySTOFactory = await DummySTOFactory.new(I_PolyToken.address, 0, 0, 0, {from:account_polymath}); - - assert.notEqual( - I_DummySTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", - "DummySTOFactory contract was not deployed" - ); - - - // 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}); - - // STEP 8: 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 }); - - // (B) : Register the GeneralDelegateManagerFactory - 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_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_MRProxied.registerModule(I_DummySTOFactory.address, { from: account_polymath }); - await I_MRProxied.verifyModule(I_DummySTOFactory.address, true, { from: account_polymath }); + [P_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` --------------------- Polymath Network Smart Contracts: --------------------- - PolymathRegistry: ${PolymathRegistry.address} - SecurityTokenRegistryProxy: ${SecurityTokenRegistryProxy.address} - SecurityTokenRegistry: ${SecurityTokenRegistry.address} - ModuleRegistryProxy ${ModuleRegistryProxy.address} - ModuleRegistry: ${ModuleRegistry.address} - FeatureRegistry: ${FeatureRegistry.address} - - STFactory: ${STFactory.address} - GeneralTransferManagerFactory: ${GeneralTransferManagerFactory.address} - GeneralPermissionManagerFactory: ${GeneralPermissionManagerFactory.address} - - DummySTOFactory: ${I_DummySTOFactory.address} + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistryProxy ${I_ModuleRegistryProxy.address} + ModuleRegistry: ${I_ModuleRegistry.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + STFactory: ${I_STFactory.address} + GeneralTransferManagerFactory: ${I_GeneralTransferManagerFactory.address} + GeneralPermissionManagerFactory: ${I_GeneralPermissionManagerFactory.address} ----------------------------------------------------------------------------- `); }); @@ -281,17 +160,12 @@ contract('GeneralPermissionManager', accounts => { I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); - it("Should successfully attach the General permission manager factory with the security token", async () => { + it("Should successfully attach the General permission manager factory with the security token -- failed because Token is not paid", async () => { let errorThrown = false; await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - try { - const tx = await I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }); - } catch(error) { - console.log(` tx -> failed because Token is not paid`.grey); - ensureException(error); - errorThrown = true; - } - assert.ok(errorThrown, message); + await catchRevert( + I_SecurityToken.addModule(P_GeneralPermissionManagerFactory.address, "0x", web3.utils.toWei("500", "ether"), 0, { from: token_owner }) + ); }); it("Should successfully attach the General permission manager factory with the security token", async () => { @@ -332,38 +206,21 @@ contract('GeneralPermissionManager', accounts => { it("Should fail in adding the delegate -- msg.sender doesn't have permission", async() => { let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}); - } catch(error) { - console.log(` tx revert -> msg.sender doesn't have permission`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: account_investor1}) + ); }); it("Should fail in adding the delegate -- no delegate details provided", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}); - } catch(error) { - console.log(` tx revert -> delegate details were not provided`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + catchRevert( + I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}) + ); }); it("Should fail to provide the permission -- because delegate is not yet added", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); - } catch(error) { - console.log(` tx revert -> Delegate is not yet added`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + await catchRevert( + I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}) + ); }); it("Should successfuly add the delegate", async() => { @@ -371,16 +228,16 @@ contract('GeneralPermissionManager', accounts => { assert.equal(tx.logs[0].args._delegate, account_delegate); }); - it("Should fail to provide the permission", async() => { - let errorThrown = false; - try { - let tx = await I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}); - } catch(error) { - console.log(` tx revert -> msg.sender doesn't have permission`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); + it("Should successfully add the delegate -- failed because trying to add the already present delegate", async() => { + await catchRevert( + I_GeneralPermissionManager.addDelegate(account_delegate, delegateDetails, { from: token_owner}) + ); + }) + + it("Should fail to provide the permission -- because msg.sender doesn't have permission", async() => { + await catchRevert( + I_GeneralPermissionManager.changePermission(account_delegate, I_GeneralTransferManager.address, "WHITELIST", true, {from: account_investor1}) + ); }); it("Should check the permission", async() => { @@ -414,12 +271,17 @@ contract('GeneralPermissionManager', accounts => { it("Should return all delegates", async() => { await I_GeneralPermissionManager.addDelegate(account_delegate2, delegateDetails, { from: token_owner}); let tx = await I_GeneralPermissionManager.getAllDelegates.call(); - console.log(tx); assert.equal(tx.length, 2); assert.equal(tx[0], account_delegate); assert.equal(tx[1], account_delegate2); }); + it("Should check is delegate for 0x address - failed 0x address is not allowed", async() => { + await catchRevert( + I_GeneralPermissionManager.checkDelegate.call("0x0000000000000000000000000000000000000000000000000") + ); + }); + it("Should return false when check is delegate - because user is not a delegate", async() => { assert.equal(await I_GeneralPermissionManager.checkDelegate.call(account_investor1), false); }); @@ -429,9 +291,32 @@ contract('GeneralPermissionManager', accounts => { }); - it("Should provide the permission in bulk", async() => { + it("Should successfully provide the permissions in batch -- failed because of array length is 0", async() => { await I_GeneralPermissionManager.addDelegate(account_delegate3, delegateDetails, { from: token_owner}); + await catchRevert( + I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}) + ); + }); + + it("Should successfully provide the permissions in batch -- failed because of perm array length is 0", async() => { + await catchRevert( + I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], [], [true, true], {from: token_owner}) + ); + }); + it("Should successfully provide the permissions in batch -- failed because mismatch in arrays length", async() => { + await catchRevert( + I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}) + ); + }); + + it("Should successfully provide the permissions in batch -- failed because mismatch in arrays length", async() => { + await catchRevert( + I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true], {from: token_owner}) + ); + }); + + it("Should successfully provide the permissions in batch", async() => { let tx = await I_GeneralPermissionManager.changePermissionMulti(account_delegate3, [I_GeneralTransferManager.address, I_GeneralPermissionManager.address], ["WHITELIST","CHANGE_PERMISSION"], [true, true], {from: token_owner}); assert.equal(tx.logs[0].args._delegate, account_delegate3); @@ -439,27 +324,26 @@ contract('GeneralPermissionManager', accounts => { assert.isTrue(await I_GeneralPermissionManager.checkPermission.call(account_delegate3, I_GeneralPermissionManager.address, "CHANGE_PERMISSION")); }); - it("Should provide all delegates with specified permission", async() => { - await I_GeneralPermissionManager.changePermission(account_delegate2, I_GeneralTransferManager.address, "WHITELIST", true, {from: token_owner}); - let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralTransferManager.address, "WHITELIST"); - // console.log(tx); assert.equal(tx.length, 3); assert.equal(tx[0], account_delegate); assert.equal(tx[1], account_delegate2); }); + it("Should get all delegates for the permission manager", async() => { + let tx = await I_GeneralPermissionManager.getAllDelegatesWithPerm.call(I_GeneralPermissionManager.address, "CHANGE_PERMISSION"); + assert.equal(tx.length, 1); + assert.equal(tx[0], account_delegate3); + }) + it("Should return all modules and all permission", async() => { - let tx = await I_GeneralPermissionManager.getAllModulesAndPermsFromTypes.call(account_delegate3, [2,1], I_SecurityToken.address); - console.log (tx); assert.equal(tx[0][0], I_GeneralTransferManager.address); assert.equal(tx[1][0], "0x57484954454c4953540000000000000000000000000000000000000000000000"); assert.equal(tx[0][1], I_GeneralPermissionManager.address); assert.equal(tx[1][1], "0x4348414e47455f5045524d495353494f4e000000000000000000000000000000"); - }); }); @@ -488,6 +372,11 @@ contract('GeneralPermissionManager', accounts => { let tags = await I_GeneralPermissionManagerFactory.getTags.call(); assert.equal(tags.length,0); }); + + it("Should ge the version of the factory", async() => { + let version = await I_GeneralPermissionManagerFactory.getVersion.call(); + assert.equal(version, "1.0.0"); + }) }); }); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 6f1272ded..4dddb81c3 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -478,7 +478,7 @@ contract("GeneralTransferManager", accounts => { it("Should set a budget for the GeneralTransferManager", async () => { await I_SecurityToken.changeModuleBudget(I_GeneralTransferManager.address, 10 * Math.pow(10, 18), { from: token_owner }); - await catchRevert(I_GeneralTransferManager.takeFee(web3.utils.toWei("1", "ether"), { from: account_polymath })); + await catchRevert(I_GeneralTransferManager.takeFee(web3.utils.toWei("1", "ether"), { from: token_owner })); await I_PolyToken.getTokens(10 * Math.pow(10, 18), token_owner); await I_PolyToken.transfer(I_SecurityToken.address, 10 * Math.pow(10, 18), { from: token_owner }); }); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 00da52285..9e061612a 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -8,10 +8,13 @@ import { setUpPolymathNetwork } from "./helpers/createInstances"; const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); +const ModuleRegistryProxy = artifacts.require("./ModuleRegistryProxy.sol"); +const ModuleRegistry = artifacts.require("./ModuleRegistry.sol"); const GeneralPermissionManagerFactory = artifacts.require("./GeneralPermissionManagerFactory.sol"); const GeneralTransferManagerFactory = artifacts.require("./GeneralTransferManagerFactory.sol"); const MockFactory = artifacts.require("./MockFactory.sol"); const TestSTOFactory = artifacts.require("./TestSTOFactory.sol"); +const ReclaimTokens = artifacts.require("./ReclaimTokens.sol"); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -47,9 +50,11 @@ contract("ModuleRegistry", accounts => { let I_SecurityTokenRegistry; let I_CappedSTOFactory1; let I_CappedSTOFactory2; + let I_CappedSTOFactory3; let I_STFactory; let I_MRProxied; let I_SecurityToken; + let I_ReclaimERC20; let I_STRProxied; let I_CappedSTO; let I_PolyToken; @@ -115,7 +120,7 @@ contract("ModuleRegistry", accounts => { I_STRProxied ] = instances; - I_GeneralTransferManagerFactory = await GeneralTransferManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); + I_ModuleRegistryProxy = await ModuleRegistryProxy.new({from: account_polymath}); // Printing all the contract addresses console.log(` @@ -133,6 +138,57 @@ contract("ModuleRegistry", accounts => { `); }); + describe("Test the initialize the function", async () => { + it("Should successfully update the implementation address -- fail because polymathRegistry address is 0x", async () => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [ + "0x0000000000000000000000000000000000000000", + account_polymath + ]); + catchRevert( + I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { + from: account_polymath + }), + "tx-> revert because polymathRegistry address is 0x" + ); + }); + + it("Should successfully update the implementation address -- fail because owner address is 0x", async () => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [ + I_PolymathRegistry.address, + "0x0000000000000000000000000000000000000000" + ]); + catchRevert( + I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { + from: account_polymath + }), + "tx-> revert because owner address is 0x" + ); + }); + + it("Should successfully update the implementation address -- fail because all params are 0x", async () => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [ + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000" + ]); + catchRevert( + I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { + from: account_polymath + }), + "tx-> revert because all params are 0x" + ); + }); + + it("Should successfully update the implementation address", async() => { + let bytesProxy = encodeProxyCall(MRProxyParameters, [ + I_PolymathRegistry.address, + account_polymath + ]); + await I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { from: account_polymath }); + I_MRProxied = await ModuleRegistry.at(I_ModuleRegistryProxy.address); + await I_PolymathRegistry.changeAddress("ModuleRegistry", I_ModuleRegistryProxy.address, { from: account_polymath }); + }) + }); + describe("Test cases for the ModuleRegistry", async () => { describe("Test case for the upgradeFromregistry", async () => { it("Should successfully update the registry contract address -- failed because of bad owner", async () => { @@ -191,8 +247,8 @@ contract("ModuleRegistry", accounts => { assert.equal(tx.logs[0].args._owner, account_polymath, "Should be the right owner"); let _list = await I_MRProxied.getModulesByType(transferManagerKey); - assert.equal(_list.length, 2, "Length should be 2"); - assert.equal(_list[1], I_GeneralTransferManagerFactory.address); + assert.equal(_list.length, 1, "Length should be 1"); + assert.equal(_list[0], I_GeneralTransferManagerFactory.address); let _reputation = await I_MRProxied.getReputationByFactory(I_GeneralTransferManagerFactory.address); assert.equal(_reputation.length, 0); @@ -205,8 +261,22 @@ contract("ModuleRegistry", accounts => { it("Should fail in registering the module-- type = 0", async () => { I_MockFactory = await MockFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath }); - await catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); + catchRevert(I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath })); + }); + + it("Should fail to register the new module because msg.sender is not the owner of the module", async() => { + I_CappedSTOFactory3 = await CappedSTOFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_temp }); + catchRevert( + I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: token_owner }) + ); }); + + it("Should successfully register the module -- fail because no module type uniqueness", async() => { + await I_MockFactory.changeTypes({from: account_polymath }); + catchRevert( + I_MRProxied.registerModule(I_MockFactory.address, { from: account_polymath }) + ); + }) }); describe("Test case for verifyModule", async () => { @@ -294,6 +364,16 @@ contract("ModuleRegistry", accounts => { assert.equal(_reputation.length, 1); }); + it("Should successfully add module when custom modules switched on -- fail because factory owner is different", async() => { + await I_MRProxied.registerModule(I_CappedSTOFactory3.address, { from: account_temp }) + startTime = latestTime() + duration.seconds(5000); + endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, fundRaiseType, account_fundsReceiver]); + catchRevert( + I_SecurityToken.addModule(I_CappedSTOFactory3.address, bytesSTO, 0, 0, { from: token_owner }) + ); + }) + it("Should successfully add verified module", async () => { I_GeneralPermissionManagerFactory = await GeneralPermissionManagerFactory.new(I_PolyToken.address, 0, 0, 0, { from: account_polymath @@ -398,25 +478,27 @@ contract("ModuleRegistry", accounts => { let sto1 = (await I_MRProxied.getModulesByType.call(3))[0]; let sto2 = (await I_MRProxied.getModulesByType.call(3))[1]; + let sto3 = (await I_MRProxied.getModulesByType.call(3))[2]; + let sto4 = (await I_MRProxied.getModulesByType.call(3))[3]; assert.equal(sto1, I_CappedSTOFactory1.address); assert.equal(sto2, I_CappedSTOFactory2.address); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 4); - let tx = await I_MRProxied.removeModule(sto1, { from: account_polymath }); + let tx = await I_MRProxied.removeModule(sto4, { from: account_polymath }); - assert.equal(tx.logs[0].args._moduleFactory, sto1, "Event is not properly emitted for _moduleFactory"); + assert.equal(tx.logs[0].args._moduleFactory, sto4, "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.getModulesByType.call(3))[1]; + let sto3_end = (await I_MRProxied.getModulesByType.call(3))[2]; // re-ordering - assert.equal(sto2_end, sto2); + assert.equal(sto3_end, sto3); // delete related data - assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto1)), 0); - assert.equal(await I_MRProxied.getReputationByFactory.call(sto1), 0); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); - assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto1)), false); + assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto4)), 0); + assert.equal(await I_MRProxied.getReputationByFactory.call(sto4), 0); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto4)), false); await revertToSnapshot(snap); }); @@ -427,7 +509,7 @@ contract("ModuleRegistry", accounts => { assert.equal(sto1, I_CappedSTOFactory1.address); assert.equal(sto2, I_CappedSTOFactory2.address); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 4); let tx = await I_MRProxied.removeModule(sto2, { from: token_owner }); @@ -441,7 +523,7 @@ contract("ModuleRegistry", accounts => { // delete related data assert.equal(await I_MRProxied.getUintValues.call(web3.utils.soliditySha3("registry", sto2)), 0); assert.equal(await I_MRProxied.getReputationByFactory.call(sto2), 0); - assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 2); + assert.equal((await I_MRProxied.getModulesByType.call(3)).length, 3); assert.equal(await I_MRProxied.getBoolValues.call(web3.utils.soliditySha3("verified", sto2)), false); }); @@ -452,6 +534,20 @@ contract("ModuleRegistry", accounts => { describe("Test cases for IRegistry functionality", async () => { describe("Test cases for reclaiming funds", async () => { + + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { + await I_PolyToken.transfer(I_MRProxied.address, web3.utils.toWei("1"), { from: token_owner }); + catchRevert( + I_MRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) + ); + }); + + it("Should successfully reclaim POLY tokens -- not authorised", async() => { + catchRevert( + I_MRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) + ); + }); + it("Should successfully reclaim POLY tokens", async () => { await I_PolyToken.getTokens(web3.utils.toWei("1"), I_MRProxied.address); let bal1 = await I_PolyToken.balanceOf.call(account_polymath); @@ -485,6 +581,48 @@ contract("ModuleRegistry", accounts => { assert.isNotOk(status); }); }); + + describe("Test cases for the ReclaimTokens contract", async() => { + + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { + I_ReclaimERC20 = await ReclaimTokens.at(I_FeatureRegistry.address); + await I_PolyToken.transfer(I_ReclaimERC20.address, web3.utils.toWei("1"), { from: token_owner }); + catchRevert( + I_ReclaimERC20.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) + ); + }); + + it("Should successfully reclaim POLY tokens -- not authorised", async() => { + catchRevert( + I_ReclaimERC20.reclaimERC20(I_PolyToken.address, { from: account_temp }) + ); + }); + + it("Should successfully reclaim POLY tokens", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1"), I_ReclaimERC20.address); + let bal1 = await I_PolyToken.balanceOf.call(account_polymath); + await I_ReclaimERC20.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() + ); + }); + }) + + describe("Test case for the PolymathRegistry", async() => { + + it("Should successfully get the address -- fail because key is not exist", async() => { + catchRevert( + I_PolymathRegistry.getAddress("PolyOracle") + ); + }); + + it("Should successfully get the address", async() => { + let _moduleR = await I_PolymathRegistry.getAddress("ModuleRegistry"); + assert.equal(_moduleR, I_ModuleRegistryProxy.address); + }) + }) }); }); }); diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index dc5fc80d5..f31344214 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -255,6 +255,23 @@ contract("SecurityTokenRegistry", accounts => { ); }); + it("Should successfully update the implementation address -- fail because all params get 0", async () => { + let bytesProxy = encodeProxyCall(STRProxyParameters, [ + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000", + 0, + 0, + "0x0000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000" + ]); + catchRevert( + I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { + from: account_polymath + }), + "tx-> revert because owner address is 0x" + ); + }); + it("Should successfully update the implementation address", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, @@ -343,6 +360,15 @@ contract("SecurityTokenRegistry", accounts => { assert.equal(tx.logs[0].args._ticker, symbol, `Symbol should be ${symbol}`); }); + it("Should register the ticker when the tickerRegFee is 0", async() => { + let snap_Id = await takeSnapshot(); + await I_STRProxied.changeTickerRegistrationFee(0, { from: account_polymath }); + let tx = await I_STRProxied.registerTicker(account_temp, "ZERO", name, { from: account_temp }); + assert.equal(tx.logs[0].args._owner, account_temp, `Owner should be the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "ZERO", `Symbol should be ZERO`); + await revertToSnapshot(snap_Id); + }) + it("Should fail to register same symbol again", async () => { // Give POLY to token issuer await I_PolyToken.getTokens(initRegFee, token_owner); @@ -475,7 +501,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should fail to generate the securityToken -- Because msg.sender is not the rightful owner of the ticker", async () => { catchRevert( - I_STRProxied.generateSecurityToken("", symbol, tokenDetails, false, { from: account_temp }), + I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: account_temp }), "tx revert -> Because msg.sender is not the rightful owner of the ticker" ); }); @@ -502,6 +528,27 @@ contract("SecurityTokenRegistry", accounts => { "tx revert -> Because ticker is already in use" ); }); + + it("Should fail to generate the SecurityToken because ticker gets expired", async() => { + let snap_Id = await takeSnapshot(); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); + await increaseTime(duration.days(65)); + catchRevert( + I_STRProxied.generateSecurityToken(name, "CCC", tokenDetails, false, { from: token_owner }), + "tx revert -> Because ticker is expired" + ); + await revertToSnapshot(snap_Id); + }); + + it("Should generate the SecurityToken when launch fee is 0", async() => { + let snap_Id = await takeSnapshot(); + await I_STRProxied.changeSecurityLaunchFee(0, { from: account_polymath }); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("500"), { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, "CCC", name, { from: token_owner }); + await I_STRProxied.generateSecurityToken(name, "CCC", tokenDetails, false, { from: token_owner }), + await revertToSnapshot(snap_Id); + }); }); describe("Generate SecurityToken v2", async () => { @@ -597,6 +644,15 @@ contract("SecurityTokenRegistry", accounts => { ); }); + it("Should fail to genrate the custom security token -- ticker length is greater than 10 chars", async() => { + catchRevert( + I_STRProxied.modifySecurityToken("LOGAN", "LOGLOGLOGLOG", account_temp, dummy_token, "I am custom ST", latestTime(), { + from: account_polymath + }), + "tx revert -> msg.sender is not polymath account" + ); + }) + it("Should fail to generate the custom security token -- name should not be 0 length ", async () => { catchRevert( I_STRProxied.modifySecurityToken("", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), { @@ -678,6 +734,12 @@ contract("SecurityTokenRegistry", accounts => { assert.equal(symbolDetails[0], account_temp, `Owner of the symbol should be ${account_temp}`); assert.equal(symbolDetails[3], "LOGAN2", `Name of the symbol should be LOGAN`); }); + + it("Should successfully modify the ticker", async() => { + let snap_Id = await takeSnapshot(); + let tx = await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(60), false, {from: account_polymath}); + await revertToSnapshot(snap_Id); + }) }); describe("Test case for modifyTicker", async () => { @@ -1026,10 +1088,23 @@ contract("SecurityTokenRegistry", accounts => { }); describe("Test cases for IRegistry functionality", async () => { describe("Test cases for reclaiming funds", async () => { - it("Should successfully reclaim POLY tokens", async () => { + + it("Should successfully reclaim POLY tokens -- fail because token address will be 0x", async() => { I_PolyToken.transfer(I_STRProxied.address, web3.utils.toWei("1"), { from: token_owner }); + catchRevert( + I_STRProxied.reclaimERC20("0x000000000000000000000000000000000000000", { from: account_polymath }) + ); + }); + + it("Should successfully reclaim POLY tokens -- not authorised", async() => { + catchRevert( + I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_temp }) + ); + }); + + it("Should successfully reclaim POLY tokens", async () => { let bal1 = await I_PolyToken.balanceOf.call(account_polymath); - await I_STRProxied.reclaimERC20(I_PolyToken.address); + await I_STRProxied.reclaimERC20(I_PolyToken.address, { from: account_polymath }); let bal2 = await I_PolyToken.balanceOf.call(account_polymath); assert.isAtLeast( bal2.dividedBy(new BigNumber(10).pow(18)).toNumber(), @@ -1059,5 +1134,57 @@ contract("SecurityTokenRegistry", accounts => { assert.isNotOk(status); }); }); + + describe("Test cases for the setProtocolVersion", async() => { + + it("Should successfully change the protocolVersion -- failed because of bad owner", async() => { + catchRevert( + I_STRProxied.setProtocolVersion(accounts[8], 5, 6, 7, { from: account_temp }) + ); + }); + + it("Should successfully change the protocolVersion -- failed because factory address is 0x", async() => { + catchRevert( + I_STRProxied.setProtocolVersion("0x000000000000000000000000000000000000000", 5, 6, 7, { from: account_polymath }) + ); + }); + + it("Should successfully change the protocolVersion -- not a valid vesrion", async() => { + catchRevert( + I_STRProxied.setProtocolVersion(accounts[8], 0, 0, 0, { from: account_polymath }) + ); + }); + + it("Should successfully change the protocolVersion -- fail in second attempt because of invalid version", async() => { + let snap_Id = await takeSnapshot(); + await I_STRProxied.setProtocolVersion(accounts[8], 1, 2, 1, {from: account_polymath }); + await catchRevert( + I_STRProxied.setProtocolVersion(accounts[8], 0, 2, 1, {from: account_polymath }) + ); + await revertToSnapshot(snap_Id); + }); + + }); + + describe("Test cases for the transferOwnership", async() => { + + it("Should fail to transfer the ownership -- not authorised", async() => { + catchRevert( + I_STRProxied.transferOwnership(account_temp, { from: account_issuer}) + ); + }); + + it("Should fail to transfer the ownership -- 0x address is not allowed", async() => { + catchRevert( + I_STRProxied.transferOwnership("0x000000000000000000000000000000000000000", { from: account_polymath}) + ); + }); + + it("Should successfully transfer the ownership of the STR", async() => { + let tx = await I_STRProxied.transferOwnership(account_temp, { from: account_polymath }); + assert.equal(tx.logs[0].args.previousOwner, account_polymath); + assert.equal(tx.logs[0].args.newOwner, account_temp); + }); + }) }); }); diff --git a/test/o_security_token.js b/test/o_security_token.js index b5ca2dbdf..6ea14c5b3 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -380,6 +380,15 @@ contract("SecurityToken", accounts => { await revertToSnapshot(key); }); + it("Should successfully archive the module first and fail during achiving the module again", async() => { + let key = await takeSnapshot(); + await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from: token_owner }); + await catchRevert( + I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from: token_owner }) + ); + await revertToSnapshot(key); + }); + it("Should verify the revertion of snapshot works properly", async () => { let moduleData = await I_SecurityToken.getModule.call(I_GeneralTransferManager.address); assert.equal(web3.utils.toAscii(moduleData[0]).replace(/\u0000/g, ""), "GeneralTransferManager"); @@ -416,6 +425,18 @@ contract("SecurityToken", accounts => { assert.equal(moduleData[3], false); }); + it("Should successfully unarchive the general transfer manager module from the securityToken -- fail because module is already unarchived", async () => { + await catchRevert( + I_SecurityToken.unarchiveModule(I_GeneralTransferManager.address, { from: token_owner }) + ); + }); + + it("Should successfully archive the module -- fail because module is not existed", async() => { + await catchRevert( + I_SecurityToken.archiveModule(I_GeneralPermissionManagerFactory.address, { from: token_owner }) + ); + }) + it("Should fail to mint tokens while GTM unarchived", async () => { await catchRevert(I_SecurityToken.mint(1, 100 * Math.pow(10, 18), { from: token_owner, gas: 500000 })); }); @@ -805,12 +826,12 @@ contract("SecurityToken", accounts => { describe("Withdraw Poly", async () => { it("Should successfully withdraw the poly", async () => { - await catchRevert(I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), { from: account_temp })); + await catchRevert(I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("20000", "ether"), { from: account_temp })); }); it("Should successfully withdraw the poly", async () => { let balanceBefore = await I_PolyToken.balanceOf(token_owner); - await I_SecurityToken.withdrawPoly(web3.utils.toWei("20000", "ether"), { from: token_owner }); + await I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("20000", "ether"), { from: token_owner }); let balanceAfter = await I_PolyToken.balanceOf(token_owner); assert.equal( BigNumber(balanceAfter) @@ -821,7 +842,7 @@ contract("SecurityToken", accounts => { }); it("Should successfully withdraw the poly", async () => { - await catchRevert(I_SecurityToken.withdrawPoly(web3.utils.toWei("10", "ether"), { from: token_owner })); + await catchRevert(I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("10", "ether"), { from: token_owner })); }); }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 73856e2cf..c6ec2dc6d 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -371,6 +371,22 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); }); + it("Should successfully call the modifyTimes before starting the STO -- fail because of bad owner", async() => { + await catchRevert( + I_USDTieredSTO_Array[0].modifyTimes(latestTime() + duration.days(15), latestTime() + duration.days(55), { from: POLYMATH }) + ); + }) + + it("Should successfully call the modifyTimes before starting the STO", async() => { + let snapId = await takeSnapshot(); + let _startTime = latestTime() + duration.days(15); + let _endTime = latestTime() + duration.days(55) + await I_USDTieredSTO_Array[0].modifyTimes(_startTime, _endTime, { from: ISSUER }); + assert.equal(await I_USDTieredSTO_Array[0].startTime.call(), _startTime, "Incorrect _startTime in config"); + assert.equal(await I_USDTieredSTO_Array[0].endTime.call(), _endTime, "Incorrect _endTime in config"); + await revertToSnapshot(snapId); + }); + it("Should successfully attach the second STO module to the security token", async () => { let stoId = 1; // No discount diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index b1af22535..7aabd338c 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -51,6 +51,7 @@ contract("TrackedRedemption", accounts => { let I_PolyToken; let I_MRProxied; let I_PolymathRegistry; + let P_TrackedRedemptionFactory; // SecurityToken Details const name = "Team"; @@ -104,6 +105,7 @@ contract("TrackedRedemption", accounts => { // STEP 4: Deploy the TrackedRedemption [I_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_TrackedRedemptionFactory] = await deployRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` @@ -153,6 +155,20 @@ contract("TrackedRedemption", accounts => { I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); + it("Should successfully attach the paid TrackedRedemption with the security token", async () => { + let snapId = await takeSnapshot(); + await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", web3.utils.toWei("500"), 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "TrackedRedemption", + "TrackedRedemption module was not added" + ); + I_TrackedRedemption = TrackedRedemption.at(tx.logs[2].args._module); + await revertToSnapshot(snapId); + }); + it("Should successfully attach the TrackedRedemption with the security token", async () => { const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", 0, 0, { from: token_owner }); assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); From 32b38eba1631632bf7ce42f3bce8186cf66de149 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 16 Oct 2018 00:37:33 +0530 Subject: [PATCH 2/6] increase coverage of transferManagers --- .solcover.js | 2 +- .../ManualApprovalTransferManager.sol | 2 +- contracts/proxy/OwnedUpgradeabilityProxy.sol | 2 +- test/b_capped_sto.js | 89 ++++++++++++--- test/d_count_transfer_manager.js | 25 +++++ test/g_general_permission_manager.js | 2 +- test/h_general_transfer_manager.js | 92 +++++++++++++++- test/j_manual_approval_transfer_manager.js | 39 ++++--- test/l_percentage_transfer_manager.js | 17 +++ test/m_presale_sto.js | 104 ++++++++++++++++++ test/p_usd_tiered_sto.js | 66 ++++++++++- test/t_security_token_registry_proxy.js | 8 ++ test/v_tracked_redemptions.js | 8 +- ...kup_volume_restriction_transfer_manager.js | 68 +++++++----- test/x_single_trade_volume_restriction.js | 9 ++ 15 files changed, 464 insertions(+), 69 deletions(-) diff --git a/.solcover.js b/.solcover.js index a99645f37..ffd077e28 100644 --- a/.solcover.js +++ b/.solcover.js @@ -4,6 +4,6 @@ module.exports = { copyPackages: ['openzeppelin-solidity'], testCommand: 'node ../node_modules/.bin/truffle test `find test/*.js ! -name a_poly_oracle.js -and ! -name s_v130_to_v140_upgrade.js` --network coverage', deepSkip: true, - skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol'], + skipFiles: ['external', 'flat', 'helpers', 'mocks', 'oracles', 'libraries/KindMath.sol', 'storage'], forceParse: ['mocks', 'oracles'] }; diff --git a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol index aa3810747..1dcc9f4cd 100644 --- a/contracts/modules/TransferManager/ManualApprovalTransferManager.sol +++ b/contracts/modules/TransferManager/ManualApprovalTransferManager.sol @@ -129,7 +129,7 @@ contract ManualApprovalTransferManager is ITransferManager { require(_from != address(0), "Invalid from address"); require(_to != address(0), "Invalid to address"); require(_expiryTime > now, "Invalid expiry time"); - require(manualApprovals[_from][_to].expiryTime == 0, "Blocking already exists"); + require(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists"); manualBlockings[_from][_to] = ManualBlocking(_expiryTime); emit AddManualBlocking(_from, _to, _expiryTime, msg.sender); } diff --git a/contracts/proxy/OwnedUpgradeabilityProxy.sol b/contracts/proxy/OwnedUpgradeabilityProxy.sol index e1890a243..81a634ec8 100644 --- a/contracts/proxy/OwnedUpgradeabilityProxy.sol +++ b/contracts/proxy/OwnedUpgradeabilityProxy.sol @@ -80,7 +80,7 @@ contract OwnedUpgradeabilityProxy is UpgradeabilityProxy { * @return address of the current implementation */ function implementation() external ifOwner returns (address) { - _implementation(); + return _implementation(); } /** diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index d52931939..e1a9b6c13 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -221,6 +221,24 @@ contract("CappedSTO", accounts => { await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); }); + it("Should fail to launch the STO due funds reciever account 0x", async () => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], "0x0000000000000000000000000000000000000000"]); + + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + }); + + it("Should fail to launch the STO due to raise type of 0 length", async () => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [], account_fundsReceiver]); + + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + }); + it("Should fail to launch the STO due to startTime > endTime", async () => { let bytesSTO = encodeModuleCall(STOParameters, [ Math.floor(Date.now() / 1000 + 100000), @@ -242,6 +260,13 @@ contract("CappedSTO", accounts => { await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); }); + it("Should fail to launch the STO due to different value incompare to getInitFunction", async() => { + let startTime = latestTime() + duration.days(1); + let endTime = startTime + duration.days(30); + let bytesSTO = encodeModuleCall(['uint256', 'uint256', 'uint256'], [startTime, endTime, 0, ]); + await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); + }); + 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); @@ -335,8 +360,7 @@ contract("CappedSTO", accounts => { // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist(account_investor1, fromTime, toTime, expiryTime, true, { - from: account_issuer, - gas: 500000 + from: account_issuer }); assert.equal(tx.logs[0].args._investor, account_investor1, "Failed in adding the investor in whitelist"); @@ -352,10 +376,9 @@ contract("CappedSTO", accounts => { }); assert.equal((await I_CappedSTO_Array_ETH[0].getRaised.call(ETH)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1); - assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 1); - assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000); + assert.equal((await I_CappedSTO_Array_ETH[0].getTokensSold.call()).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000); }); it("Verification of the event Token Purchase", async () => { @@ -365,6 +388,14 @@ contract("CappedSTO", accounts => { assert.equal(log.args.amount.dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000, "Wrong No. token get dilivered"); }); + it("Should fail to buy the tokens -- Because fundRaiseType is ETH not POLY", async ()=> { + await I_PolyToken.getTokens(web3.utils.toWei("500"), account_investor1); + await I_PolyToken.approve(I_CappedSTO_Array_ETH[0].address, web3.utils.toWei("500"), {from: account_investor1}); + await catchRevert( + I_CappedSTO_Array_ETH[0].buyTokensWithPoly(web3.utils.toWei("500"), {from: account_investor1}) + ); + }) + it("Should pause the STO -- Failed due to wrong msg.sender", async () => { await catchRevert(I_CappedSTO_Array_ETH[0].pause({ from: account_investor1 })); }); @@ -413,8 +444,7 @@ contract("CappedSTO", accounts => { expiryTime, true, { - from: account_issuer, - gas: 500000 + from: account_issuer } ); @@ -433,7 +463,7 @@ contract("CappedSTO", accounts => { assert.equal(await I_CappedSTO_Array_ETH[0].investorCount.call(), 2); assert.equal((await I_SecurityToken_ETH.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 9000); - await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor2, { value: web3.utils.toWei("100") })); + await catchRevert(I_CappedSTO_Array_ETH[0].buyTokens(account_investor2, { value: web3.utils.toWei("81") })); }); it("Should fundRaised value equal to the raised value in the funds receiver wallet", async () => { @@ -477,7 +507,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); await I_CappedSTO_Array_ETH[0].reclaimERC20(I_PolyToken.address, { from: token_owner }); assert.equal( - (await I_PolyToken.balanceOf(account_investor3)).toNumber(), + (await I_PolyToken.balanceOf(account_investor1)).toNumber(), initInvestorBalance.toNumber(), "tokens are not transfered out from investor account" ); @@ -559,6 +589,12 @@ contract("CappedSTO", accounts => { assert.equal(allow, true, "allowBeneficialInvestments should be true"); }); + it("Should allow non-matching beneficiary -- failed because it is already active", async () => { + await catchRevert( + I_CappedSTO_Array_ETH[1].changeAllowBeneficialInvestments(true, { from: account_issuer }) + ); + }); + it("Should invest in second STO", async () => { await I_CappedSTO_Array_ETH[1].buyTokens(account_investor3, { from: account_issuer, value: web3.utils.toWei("1", "ether") }); @@ -692,7 +728,7 @@ contract("CappedSTO", accounts => { blockNo = latestBlock(); assert.equal( (await I_PolyToken.balanceOf(account_investor1)).dividedBy(new BigNumber(10).pow(18)).toNumber(), - 10000, + 10500, "Tokens are not transfered properly" ); @@ -710,8 +746,7 @@ contract("CappedSTO", accounts => { // buyTokensWithPoly transaction await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { - from: account_investor1, - gas: 6000000 + from: account_investor1 }); assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 1000); @@ -731,6 +766,33 @@ contract("CappedSTO", accounts => { assert.equal(log.args.amount.dividedBy(new BigNumber(10).pow(18)).toNumber(), 5000, "Wrong No. token get dilivered"); }); + it("Should failed to buy tokens -- because fundraisetype is POLY not ETH", async() => { + await catchRevert( + // Fallback transaction + web3.eth.sendTransaction({ + from: account_investor1, + to: I_CappedSTO_Array_POLY[0].address, + gas: 2100000, + value: web3.utils.toWei("2", "ether") + }) + ); + }); + + it("Should fail in buying tokens because buying is paused", async() => { + await I_CappedSTO_Array_POLY[0].pause({ from: account_issuer }); + await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 1000 * Math.pow(10, 18), { from: account_investor1 }); + + // buyTokensWithPoly transaction + await catchRevert( + I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { + from: account_investor1, + gas: 6000000 + }) + ); + await I_CappedSTO_Array_POLY[0].unpause({ from: account_issuer }); + }); + + it("Should restrict to buy tokens after hiting the cap in second tx first tx pass", async () => { let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor2, @@ -751,7 +813,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 9000 * Math.pow(10, 18), { from: account_investor2 }); // buyTokensWithPoly transaction - await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(9000 * Math.pow(10, 18), { from: account_investor2, gas: 6000000 }); + await I_CappedSTO_Array_POLY[0].buyTokensWithPoly(9000 * Math.pow(10, 18), { from: account_investor2 }); assert.equal((await I_CappedSTO_Array_POLY[0].getRaised.call(POLY)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 10000); @@ -763,7 +825,7 @@ contract("CappedSTO", accounts => { ); await I_PolyToken.approve(I_CappedSTO_Array_POLY[0].address, 1000 * Math.pow(10, 18), { from: account_investor1 }); await catchRevert( - I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { from: account_investor1, gas: 6000000 }) + I_CappedSTO_Array_POLY[0].buyTokensWithPoly(1000 * Math.pow(10, 18), { from: account_investor1 }) ); }); @@ -803,6 +865,7 @@ contract("CappedSTO", accounts => { ); let tags = await I_CappedSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "Capped"); + assert.equal(await I_CappedSTOFactory.getVersion.call(), "1.0.0"); }); it("Should fail to change the title -- bad owner", async () => { diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 97e09461b..de38c2f28 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -249,6 +249,31 @@ contract("CountTransferManager", accounts => { assert.equal((await I_SecurityToken.balanceOf(account_investor2)).toNumber(), web3.utils.toWei("2", "ether")); }); + it("Should able to buy some more tokens (more than 2 hoders) -- because CountTransferManager is paused", async() => { + await I_CountTransferManager.pause({from: account_issuer }); + let snapId = await takeSnapshot(); + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor3.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + await I_SecurityToken.mint(account_investor3, web3.utils.toWei("3", "ether"), { from: token_owner }) + await revertToSnapshot(snapId); + }) + it("Should fail to buy some more tokens (more than 2 holders)", async () => { // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( diff --git a/test/g_general_permission_manager.js b/test/g_general_permission_manager.js index b7dcb7880..eb22406c8 100644 --- a/test/g_general_permission_manager.js +++ b/test/g_general_permission_manager.js @@ -210,7 +210,7 @@ contract('GeneralPermissionManager', accounts => { it("Should fail in adding the delegate -- no delegate details provided", async() => { catchRevert( - I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: account_investor1}) + I_GeneralPermissionManager.addDelegate(account_delegate, '', { from: token_owner }) ); }); diff --git a/test/h_general_transfer_manager.js b/test/h_general_transfer_manager.js index 4dddb81c3..c40809d8b 100644 --- a/test/h_general_transfer_manager.js +++ b/test/h_general_transfer_manager.js @@ -5,7 +5,7 @@ import { signData } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed } from "./helpers/createInstances"; +import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed, deployGTMAndVerifyed } from "./helpers/createInstances"; const DummySTO = artifacts.require("./DummySTO.sol"); @@ -49,6 +49,7 @@ contract("GeneralTransferManager", accounts => { let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_DummySTOFactory; + let P_DummySTOFactory; let I_STFactory; let I_SecurityToken; let I_STRProxied; @@ -56,6 +57,7 @@ contract("GeneralTransferManager", accounts => { let I_DummySTO; let I_PolyToken; let I_PolymathRegistry; + let P_GeneralTransferManagerFactory; // SecurityToken Details const name = "Team"; @@ -113,7 +115,9 @@ contract("GeneralTransferManager", accounts => { ] = instances; [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_GeneralTransferManagerFactory] = await deployGTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); [I_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [P_DummySTOFactory] = await deployDummySTOAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); // Printing all the contract addresses console.log(` @@ -164,6 +168,19 @@ contract("GeneralTransferManager", accounts => { I_GeneralTransferManager = GeneralTransferManager.at(moduleData); }); + it("Should attach the paid GTM -- failed because of no tokens", async() => { + await catchRevert( + I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}) + ); + }) + + it("Should attach the paid GTM", async() => { + let snap_id = await takeSnapshot(); + await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); + await I_SecurityToken.addModule(P_GeneralTransferManagerFactory.address, "", web3.utils.toWei("500"), 0, {from: account_issuer}); + await revertToSnapshot(snap_id); + }) + it("Should whitelist the affiliates before the STO attached", async () => { let tx = await I_GeneralTransferManager.modifyWhitelistMulti( [account_affiliates1, account_affiliates2], @@ -189,6 +206,49 @@ contract("GeneralTransferManager", accounts => { assert.equal((await I_SecurityToken.balanceOf.call(account_affiliates2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); }); + + it("Should successfully attach the STO factory with the security token -- failed because of no tokens", async () => { + let bytesSTO = encodeModuleCall(STOParameters, [ + latestTime() + duration.seconds(1000), + latestTime() + duration.days(40), + cap, + someString + ]); + await catchRevert( + I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: token_owner }) + ); + }); + + it("Should successfully attach the STO factory with the security token", async () => { + let snap_id = await takeSnapshot(); + let bytesSTO = encodeModuleCall(STOParameters, [ + latestTime() + duration.seconds(1000), + latestTime() + duration.days(40), + cap, + someString + ]); + await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), stoKey, "DummySTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), + "DummySTO", + "DummySTOFactory module was not added" + ); + I_DummySTO = DummySTO.at(tx.logs[3].args._module); + await revertToSnapshot(snap_id); + }); + + it("Should successfully attach the STO factory with the security token - invalid data", async () => { + let bytesSTO = encodeModuleCall(['uint256', 'string'], [ + latestTime() + duration.seconds(1000), + someString + ]); + await catchRevert( + I_SecurityToken.addModule(P_DummySTOFactory.address, bytesSTO, 0, 0, { from: token_owner }) + ); + }); + it("Should successfully attach the STO factory with the security token", async () => { let bytesSTO = encodeModuleCall(STOParameters, [ latestTime() + duration.seconds(1000), @@ -257,6 +317,24 @@ contract("GeneralTransferManager", accounts => { await catchRevert(I_DummySTO.generateTokens(account_affiliates1, web3.utils.toWei("1", "ether"), { from: token_owner })); }); + it("Should fail in buying the tokens from the STO -- because amount is 0", async() => { + await catchRevert( + I_DummySTO.generateTokens(account_investor1, 0, { from: token_owner }) + ); + }); + + it("Should fail in buying the tokens from the STO -- because STO is paused", async() => { + await I_DummySTO.pause({from: account_issuer }); + await catchRevert(I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner })); + // Reverting the changes releated to pause + await I_DummySTO.unpause({from: account_issuer }); + }); + + it("Should buy more tokens from the STO to investor1", async() => { + await I_DummySTO.generateTokens(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("2", "ether")); + }); + it("Should fail in investing the money in STO -- expiry limit reached", async () => { await increaseTime(duration.days(10)); @@ -646,6 +724,7 @@ contract("GeneralTransferManager", accounts => { "Allows an issuer to maintain a time based whitelist of authorised token holders.Addresses are added via modifyWhitelist, and take a fromTime (the time from which they can send tokens) and a toTime (the time from which they can receive tokens). There are additional flags, allowAllWhitelistIssuances, allowAllWhitelistTransfers & allowAllTransfers which allow you to set corresponding contract level behaviour. Init function takes no parameters.", "Wrong Module added" ); + assert.equal(await I_GeneralPermissionManagerFactory.getVersion.call(), "1.0.0"); }); it("Should get the tags of the factory", async () => { @@ -672,6 +751,11 @@ contract("GeneralTransferManager", accounts => { let tags = await I_DummySTOFactory.getTags.call(); assert.equal(web3.utils.toAscii(tags[0]).replace(/\u0000/g, ""), "Dummy"); }); + + it("Should get the version of factory", async() => { + let version = await I_DummySTOFactory.getVersion.call(); + assert.equal(version, "1.0.0"); + }); }); describe("Test cases for the get functions of the dummy sto", async () => { @@ -684,12 +768,16 @@ contract("GeneralTransferManager", accounts => { }); it("Should get the investors", async () => { - assert.equal((await I_DummySTO.investorCount.call()).toNumber(), 2); + assert.equal((await I_DummySTO.getNumberInvestors.call()).toNumber(), 2); }); it("Should get the listed permissions", async () => { let tx = await I_DummySTO.getPermissions.call(); assert.equal(web3.utils.toAscii(tx[0]).replace(/\u0000/g, ""), "ADMIN"); }); + + it("Should get the amount of tokens sold", async() => { + assert.equal(await I_DummySTO.getTokensSold.call(), 0); + }) }); }); diff --git a/test/j_manual_approval_transfer_manager.js b/test/j_manual_approval_transfer_manager.js index 61472e4ff..0a1346f31 100644 --- a/test/j_manual_approval_transfer_manager.js +++ b/test/j_manual_approval_transfer_manager.js @@ -302,12 +302,15 @@ contract("ManualApprovalTransferManager", accounts => { account_investor3.toLowerCase(), "Failed in adding the investor in whitelist" ); - + // Pause at the transferManager level + await I_ManualApprovalTransferManager.pause({from: token_owner}); // Add the Investor in to the whitelist // Mint some tokens await I_SecurityToken.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); assert.equal((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("1", "ether")); + // Unpause at the transferManager level + await I_ManualApprovalTransferManager.unpause({from: token_owner}); }); it("Should still be able to transfer between existing token holders", async () => { @@ -364,6 +367,18 @@ contract("ManualApprovalTransferManager", accounts => { ); }); + it("Should fail to add a manual approval because allowance is laready exists", async () => { + await catchRevert( + I_ManualApprovalTransferManager.addManualApproval( + account_investor1, + account_investor4, + web3.utils.toWei("2", "ether"), + latestTime() + duration.days(5), + { from: token_owner } + ) + ); + }); + it("Should fail to revoke manual approval because invalid _from address", async () => { await catchRevert(I_ManualApprovalTransferManager.revokeManualApproval("", account_investor4, { from: token_owner })); }); @@ -452,6 +467,12 @@ contract("ManualApprovalTransferManager", accounts => { }); }); + it("Should fail to add a manual block because blocking already exist", async () => { + await catchRevert( + I_ManualApprovalTransferManager.addManualBlocking(account_investor1, account_investor2, latestTime() + duration.days(5), { from: token_owner }) + ); + }); + it("Check manual block causes failure", async () => { await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); }); @@ -507,21 +528,6 @@ contract("ManualApprovalTransferManager", accounts => { assert.equal(perm.length, 1); }); - // it("Check manual approval has a higher priority than an INVALID result from another TM", async() => { - // //Should fail initial transfer - // - // try { - // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - // } catch(error) { - // console.log(`Failed due to to count block`); - // ensureException(error); - // errorThrown = true; - // } - // //Add a manual approval - transfer should now work - // await I_ManualApprovalTransferManager.addManualApproval(account_investor2, account_investor5, web3.utils.toWei('1', 'ether'), latestTime() + duration.days(1), { from: token_owner }); - // await I_SecurityToken.transfer(account_investor5, web3.utils.toWei('1', 'ether'), { from: account_investor2 }); - // }); - it("Should get the init function", async () => { let byte = await I_ManualApprovalTransferManager.getInitFunction.call(); assert.equal(web3.utils.toAscii(byte).replace(/\u0000/g, ""), 0); @@ -544,6 +550,7 @@ contract("ManualApprovalTransferManager", accounts => { "Allows an issuer to set manual approvals or blocks for specific pairs of addresses and amounts. Init function takes no parameters.", "Wrong Module added" ); + assert.equal(await I_ManualApprovalTransferManagerFactory.getVersion.call(), "1.0.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/l_percentage_transfer_manager.js b/test/l_percentage_transfer_manager.js index c9e03ecfb..3a62463ac 100644 --- a/test/l_percentage_transfer_manager.js +++ b/test/l_percentage_transfer_manager.js @@ -320,6 +320,10 @@ contract("PercentageTransferManager", accounts => { let snapId = await takeSnapshot(); await I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }); await I_SecurityToken.mint(account_investor3, web3.utils.toWei('100', 'ether'), { from: token_owner }); + // trying to call it again with the same value. should fail + await catchRevert( + I_PercentageTransferManager.setAllowPrimaryIssuance(true, { from: token_owner }) + ) await revertToSnapshot(snapId); }); @@ -342,6 +346,18 @@ contract("PercentageTransferManager", accounts => { await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor1 }); }); + it("Should whitelist in batch --failed because of mismatch in array lengths", async() => { + await catchRevert( + I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false], { from: token_owner }) + ); + }) + + it("Should whitelist in batch", async() => { + let snapId = await takeSnapshot(); + await I_PercentageTransferManager.modifyWhitelistMulti([account_investor3, account_investor4], [false, true], { from: token_owner }); + await revertToSnapshot(snapId); + }) + it("Should be able to whitelist address and then transfer regardless of holders", async () => { await I_PercentageTransferManager.changeHolderPercentage(30 * 10 ** 16, { from: token_owner }); await I_PercentageTransferManager.modifyWhitelist(account_investor1, true, { from: token_owner }); @@ -374,6 +390,7 @@ contract("PercentageTransferManager", accounts => { "Allows an issuer to restrict the total number of non-zero token holders", "Wrong Module added" ); + assert.equal(await I_PercentageTransferManagerFactory.getVersion.call(), "1.0.0"); }); it("Should get the tags of the factory", async () => { diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index df605d86e..7f7922241 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -41,6 +41,7 @@ contract("PreSaleSTO", accounts => { let I_FeatureRegistry; let I_SecurityTokenRegistry; let I_PreSaleSTOFactory; + let P_PreSaleSTOFactory; let I_STFactory; let I_SecurityToken; let I_MRProxied; @@ -99,6 +100,8 @@ contract("PreSaleSTO", accounts => { // STEP 4: Deploy the PreSaleSTOFactory [I_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 5: Deploy the paid PresaleSTOFactory + [P_PreSaleSTOFactory] = await deployPresaleSTOAndVerified(account_polymath, I_MRProxied, I_PolyToken.address, 0); // Printing all the contract addresses console.log(` @@ -154,6 +157,46 @@ contract("PreSaleSTO", accounts => { await catchRevert(I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner })); }); + it("Should successfully attach the Paid STO factory with the security token", async () => { + let snap_id = await takeSnapshot(); + endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time + let bytesSTO = encodeModuleCall(STOParameters, [endTime]); + await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); + const tx = await I_SecurityToken.addModule(P_PreSaleSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: token_owner }); + + assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "PreSaleSTO", + "PreSaleSTOFactory module was not added" + ); + I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); + await revertToSnapshot(snap_id); + }); + + it("Should successfully attach the STO factory with the security token -- fail because signature is different", async () => { + endTime = latestTime() + duration.days(30); // Start time will be 5000 seconds more than the latest time + let bytesSTO = encodeModuleCall(["string"], ["hey"]); + await catchRevert( + I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }) + ); + }); + + 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 = encodeModuleCall(STOParameters, [endTime]); + + const tx = await I_SecurityToken.addModule(I_PreSaleSTOFactory.address, bytesSTO, 0, 0, { from: token_owner }); + + assert.equal(tx.logs[2].args._types[0], stoKey, "PreSaleSTO doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "PreSaleSTO", + "PreSaleSTOFactory module was not added" + ); + I_PreSaleSTO = PreSaleSTO.at(tx.logs[2].args._module); + }); + 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 = encodeModuleCall(STOParameters, [endTime]); @@ -211,6 +254,14 @@ contract("PreSaleSTO", accounts => { // assert.isTrue(false); }); + it("Should allocate the tokens --failed because of amount is 0", async() => { + await catchRevert( + I_PreSaleSTO.allocateTokens(account_investor1, 0, web3.utils.toWei("1", "ether"), 0, { + from: account_issuer + }) + ); + }) + it("Should allocate the tokens -- failed due to msg.sender is not pre sale admin", async () => { await catchRevert( I_PreSaleSTO.allocateTokens(account_investor1, web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether"), 0, { @@ -252,6 +303,54 @@ contract("PreSaleSTO", accounts => { assert.equal((await I_PreSaleSTO.getNumberInvestors.call()).toNumber(), 3); }); + it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + await catchRevert( + I_PreSaleSTO.allocateTokensMulti( + [account_investor2], + [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [0, 0], + [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + { from: account_issuer } + ) + ); + }) + + it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + await catchRevert( + I_PreSaleSTO.allocateTokensMulti( + [account_investor2, account_investor3], + [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [0], + [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + { from: account_issuer } + ) + ); + }); + + it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + await catchRevert( + I_PreSaleSTO.allocateTokensMulti( + [account_investor2, account_investor3], + [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [0,0], + [web3.utils.toWei("1000", "ether")], + { from: account_issuer } + ) + ); + }); + + it("Should successfully mint multiple tokens -- failed because array mismatch", async() => { + await catchRevert( + I_PreSaleSTO.allocateTokensMulti( + [account_investor2, account_investor3], + [web3.utils.toWei("1", "ether"), web3.utils.toWei("1", "ether")], + [0], + [web3.utils.toWei("1000", "ether"), web3.utils.toWei("1000", "ether")], + { from: account_issuer } + ) + ); + }); + it("Should failed at the time of buying the tokens -- Because STO has started", async () => { await increaseTime(duration.days(100)); // increased beyond the end time of the STO @@ -298,6 +397,11 @@ contract("PreSaleSTO", accounts => { "tokens are not trandfered out from STO contract" ); }); + + it("Should get the the tokens sold", async() => { + let _tokensSold = await I_PreSaleSTO.getTokensSold.call(); + console.log(_tokensSold); + }) }); describe("Test cases for the PresaleSTOFactory", async () => { diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index c6ec2dc6d..e7c1d1298 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -58,6 +58,7 @@ contract("USDTieredSTO", accounts => { let I_PolyToken; let I_DaiToken; let I_PolymathRegistry; + let P_USDTieredSTOFactory; // SecurityToken Details for funds raise Type ETH const NAME = "Team"; @@ -68,6 +69,7 @@ contract("USDTieredSTO", accounts => { // Module key const TMKEY = 2; const STOKEY = 3; + let snapId; // Initial fee for ticker registry and security token registry const REGFEE = web3.utils.toWei("250"); @@ -226,7 +228,7 @@ contract("USDTieredSTO", accounts => { // STEP 5: Deploy the USDTieredSTOFactory [I_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, I_PolyToken.address, STOSetupCost); - + [P_USDTieredSTOFactory] = await deployUSDTieredSTOAndVerified(POLYMATH, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500")); // Step 12: Deploy & Register Mock Oracles I_USDOracle = await MockOracle.new(0, "ETH", "USD", USDETH, { from: POLYMATH }); // 500 dollars per POLY I_POLYOracle = await MockOracle.new(I_PolyToken.address, "POLY", "USD", USDPOLY, { from: POLYMATH }); // 25 cents per POLY @@ -371,6 +373,67 @@ contract("USDTieredSTO", accounts => { assert.equal((await I_USDTieredSTO_Array[stoId].getPermissions()).length, 0, "Incorrect number of permissions"); }); + it("Should attach the paid STO factory -- failed because of no tokens", async() => { + let stoId = 0; // No discount + let config = [ + _startTime[stoId], + _endTime[stoId], + _ratePerTier[stoId], + _ratePerTierDiscountPoly[stoId], + _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], + _nonAccreditedLimitUSD[stoId], + _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], + _wallet[stoId], + _reserveWallet[stoId], + _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + await catchRevert( + I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }) + ); + }); + + it("Should attach the paid STO factory", async() => { + let snapId = await takeSnapshot(); + let stoId = 0; // No discount + let config = [ + _startTime[stoId], + _endTime[stoId], + _ratePerTier[stoId], + _ratePerTierDiscountPoly[stoId], + _tokensPerTierTotal[stoId], + _tokensPerTierDiscountPoly[stoId], + _nonAccreditedLimitUSD[stoId], + _minimumInvestmentUSD[stoId], + _fundRaiseTypes[stoId], + _wallet[stoId], + _reserveWallet[stoId], + _usdToken[stoId] + ]; + + let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); + await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); + let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }); + await revertToSnapshot(snapId); + }); + + it("Should allow non-matching beneficiary", async () => { + snapId = await takeSnapshot(); + await I_USDTieredSTO_Array[0].changeAllowBeneficialInvestments(true, { from: ISSUER }); + let allow = await I_USDTieredSTO_Array[0].allowBeneficialInvestments(); + assert.equal(allow, true, "allowBeneficialInvestments should be true"); + }); + + it("Should allow non-matching beneficiary -- failed because it is already active", async () => { + await catchRevert( + I_USDTieredSTO_Array[0].changeAllowBeneficialInvestments(true, { from: ISSUER }) + ); + await revertToSnapshot(snapId); + }); + it("Should successfully call the modifyTimes before starting the STO -- fail because of bad owner", async() => { await catchRevert( I_USDTieredSTO_Array[0].modifyTimes(latestTime() + duration.days(15), latestTime() + duration.days(55), { from: POLYMATH }) @@ -4245,6 +4308,7 @@ contract("USDTieredSTO", accounts => { assert.equal(await I_USDTieredSTOFactory.getDescription.call(), "USD Tiered STO", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.getTitle.call(), "USD Tiered STO", "Wrong Module added"); assert.equal(await I_USDTieredSTOFactory.getInstructions.call(), "Initialises a USD tiered STO.", "Wrong Module added"); + assert.equal(await I_USDTieredSTOFactory.getVersion.call(), "1.0.0"); let tags = await I_USDTieredSTOFactory.getTags.call(); assert.equal(web3.utils.hexToString(tags[0]), "USD"); assert.equal(web3.utils.hexToString(tags[1]), "Tiered"); diff --git a/test/t_security_token_registry_proxy.js b/test/t_security_token_registry_proxy.js index 2d426d656..40b1cced8 100644 --- a/test/t_security_token_registry_proxy.js +++ b/test/t_security_token_registry_proxy.js @@ -257,5 +257,13 @@ contract("SecurityTokenRegistryProxy", accounts => { assert.equal(await readStorage(c.address, 12), I_SecurityTokenRegistry.address, "Implemnted address is not matched"); I_STRProxied = await SecurityTokenRegistry.at(I_SecurityTokenRegistryProxy.address); }); + + it("Should get the version", async() => { + assert.equal(await I_SecurityTokenRegistryProxy.version.call({ from: account_polymath_new }), "1.2.0"); + }); + + it("Should get the implementation address", async() => { + assert.equal(await I_SecurityTokenRegistryProxy.implementation.call({ from: account_polymath_new }), I_SecurityTokenRegistry.address); + }) }); }); diff --git a/test/v_tracked_redemptions.js b/test/v_tracked_redemptions.js index 7aabd338c..a8a11f66d 100644 --- a/test/v_tracked_redemptions.js +++ b/test/v_tracked_redemptions.js @@ -158,14 +158,14 @@ contract("TrackedRedemption", accounts => { it("Should successfully attach the paid TrackedRedemption with the security token", async () => { let snapId = await takeSnapshot(); await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); - const tx = await I_SecurityToken.addModule(I_TrackedRedemptionFactory.address, "", web3.utils.toWei("500"), 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); + const tx = await I_SecurityToken.addModule(P_TrackedRedemptionFactory.address, "", web3.utils.toWei("500"), 0, { from: token_owner }); + assert.equal(tx.logs[3].args._types[0].toNumber(), burnKey, "TrackedRedemption doesn't get deployed"); assert.equal( - web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + web3.utils.toAscii(tx.logs[3].args._name).replace(/\u0000/g, ""), "TrackedRedemption", "TrackedRedemption module was not added" ); - I_TrackedRedemption = TrackedRedemption.at(tx.logs[2].args._module); + I_TrackedRedemption = TrackedRedemption.at(tx.logs[3].args._module); await revertToSnapshot(snapId); }); diff --git a/test/w_lockup_volume_restriction_transfer_manager.js b/test/w_lockup_volume_restriction_transfer_manager.js index 1caea7374..fda65be4f 100644 --- a/test/w_lockup_volume_restriction_transfer_manager.js +++ b/test/w_lockup_volume_restriction_transfer_manager.js @@ -359,7 +359,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should prevent the transfer of tokens in a lockup", async() => { let balance = await I_SecurityToken.balanceOf(account_investor2) - + console.log("balance", balance.dividedBy(new BigNumber(1).times(new BigNumber(10).pow(18))).toNumber()); // create a lockup for their entire balance // over 12 seconds total, with 3 periods of 4 seconds each. await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 12, 4, 0, balance, { from: token_owner }); @@ -377,7 +377,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should allow the transfer of tokens in a lockup if a period has passed", async() => { // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); }); @@ -392,7 +392,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { it("Should allow the transfer of more tokens in a lockup if another period has passed", async() => { // wait 4 more seconds - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(4000); await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('3', 'ether'), { from: account_investor2 }); }); @@ -402,7 +402,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { let balance = await I_SecurityToken.balanceOf(account_investor2) // wait 4 more seconds - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(4000); await I_SecurityToken.transfer(account_investor1, balance, { from: account_investor2 }); }); @@ -453,6 +453,20 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { }); + it("Should succesfully modify the lockup - fail because array index out of bound", async() => { + // balance here should be 12000000000000000000 (12e18 or 12 eth) + let balance = await I_SecurityToken.balanceOf(account_investor1); + await catchRevert( + I_VolumeRestrictionTransferManager.modifyLockUp(account_investor1, 8, 8, 4, 0, balance, { from: token_owner }) + ); + }) + + it("Should succesfully get the lockup - fail because array index out of bound", async() => { + await catchRevert( + I_VolumeRestrictionTransferManager.getLockUp(account_investor1, 9) + ); + }) + it("Should be possible to remove a lockup -- couldn't transfer because of lock up", async() => { let acct1Balance = await I_SecurityToken.balanceOf(account_investor1) @@ -478,6 +492,12 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { assert.equal(acct2BalanceAfter.sub(acct2BalanceBefore).toString(), acct1Balance.toString()) }); + it("Should try to remove the lockup --failed because of index is out of bounds", async() => { + await catchRevert( + I_VolumeRestrictionTransferManager.removeLockUp(account_investor2, 7, { from: token_owner }) + ); + }) + it("Should be possible to create multiple lockups at once", async() => { let balancesBefore = {} @@ -536,7 +556,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { assert.equal(lockUpCountsAfter[account_investor3], 1); // wait 4 seconds - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(4000); // try transfers again await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2', 'ether'), { from: account_investor2 }); @@ -576,34 +596,27 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { lockUpsLength = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); assert.equal(lockUpsLength, 0); - let now = (await web3.eth.getBlock('latest')).timestamp + let now = latestTime(); // balance here should be 10000000000000000000 let balance = await I_SecurityToken.balanceOf(account_investor2) - await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + 4, balance, { from: token_owner }); - - // try a transfer. it should fail because the lockup hasn't started yet. - await catchRevert( - I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) - ); - now = (await web3.eth.getBlock('latest')).timestamp + await I_VolumeRestrictionTransferManager.addLockUp(account_investor2, 100, 10, now + duration.seconds(4), balance, { from: token_owner }); // wait 4 seconds for the lockup to begin - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); // try another transfer. it should also fail because the lockup has just begun await catchRevert( I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), { from: account_investor2 }) ); - now = (await web3.eth.getBlock('latest')).timestamp }); it("Should be possible to edit a lockup with a specific start time in the future", async() => { // edit the lockup - let now = (await web3.eth.getBlock('latest')).timestamp + let now = latestTime(); // should be 10000000000000000000 let balance = await I_SecurityToken.balanceOf(account_investor2) @@ -621,7 +634,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { assert.equal(lockUp[3].toString(), balance.toString()); // edit the lockup - await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + 4, balance, { from: token_owner }); + await I_VolumeRestrictionTransferManager.modifyLockUp(account_investor2, 0, 8, 4, now + duration.seconds(4), balance, { from: token_owner }); // check and get the lockup again lockUpCount = await I_VolumeRestrictionTransferManager.getLockUpsLength(account_investor2); @@ -641,7 +654,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); // wait 4 seconds for the lockup to begin - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); // try another transfer. it should fail because the lockup has just begun await catchRevert( @@ -649,7 +662,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); // wait 4 seconds for the lockup's first period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); // try another transfer. it should pass await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); @@ -661,7 +674,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); // wait 4 seconds for the lockup's first period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); let lockUpBeforeVerify = await I_VolumeRestrictionTransferManager.getLockUp(account_investor2, 0); // check if transfer will pass in read-only operation @@ -676,7 +689,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('5', 'ether'), { from: account_investor2 }); // wait 4 seconds for the lockup's first period to elapse. but, we are all out of periods. - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); // try one final transfer. this should fail because the user has already withdrawn their entire balance await catchRevert( @@ -702,8 +715,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { I_SecurityToken.transfer(account_investor2, web3.utils.toWei('1', 'ether'), { from: account_investor1 }) ); // wait 4 seconds for the lockup's first period to elapse. - await new Promise(resolve => setTimeout(resolve, 4000)); - + await increaseTime(duration.seconds(4)); // should succeed await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('2', 'ether'), { from: account_investor1 }); @@ -720,7 +732,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); // wait 4 seconds for the 1st lockup's second period to elapse, and the 2nd lockup's first period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); + await increaseTime(duration.seconds(4)); // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); @@ -731,14 +743,12 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { ); // wait 4 seconds for the 1st lockup's final period to elapse, and the 2nd lockup's second period to elapse - await new Promise(resolve => setTimeout(resolve, 4000)); - + await increaseTime(duration.seconds(4)); // should now be able to transfer 4, because of 2 allowed from the 1st lockup and 2 from the 2nd await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); // wait 8 seconds for 2nd lockup's third and fourth periods to elapse - await new Promise(resolve => setTimeout(resolve, 8000)); - + await increaseTime(duration.seconds(8)); // should now be able to transfer 4, because there are 2 allowed per period in the 2nd lockup, and 2 periods have elapsed await I_SecurityToken.transfer(account_investor2, web3.utils.toWei('4', 'ether'), { from: account_investor1 }); @@ -786,7 +796,7 @@ contract('LockupVolumeRestrictionTransferManager', accounts => { assert.equal(await I_VolumeRestrictionTransferManagerFactory.getInstructions.call(), "Allows an issuer to set lockup periods for user addresses, with funds distributed over time. Init function takes no parameters.", "Wrong Module added"); - + assert.equal(await I_VolumeRestrictionTransferManagerFactory.getVersion.call(), "1.0.0"); }); it("Should get the tags of the factory", async() => { diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index f4bf8180a..34dc130dc 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -219,6 +219,15 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { ); }); + it("Should allow the primary issuance", async() => { + let snapId = await takeSnapshot(); + await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}); + await catchRevert( + I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}) + ) + await revertToSnapshot(snapId); + }) + it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); From 0db16612347888b99b8950aa7f38b6673fa5d218 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 16 Oct 2018 14:00:02 +0530 Subject: [PATCH 3/6] improve the coverage of token --- contracts/mocks/MockBurnFactory.sol | 101 ++++++++++++++ contracts/mocks/MockFactory.sol | 1 + contracts/mocks/MockRedemptionManager.sol | 75 +++++++++++ contracts/mocks/MockWrongTypeFactory.sol | 101 ++++++++++++++ contracts/modules/Burn/TrackedRedemption.sol | 2 +- test/d_count_transfer_manager.js | 1 + test/helpers/createInstances.js | 28 ++++ test/o_security_token.js | 134 ++++++++++++++++++- test/p_usd_tiered_sto.js | 4 +- test/x_single_trade_volume_restriction.js | 18 +-- 10 files changed, 452 insertions(+), 13 deletions(-) create mode 100644 contracts/mocks/MockBurnFactory.sol create mode 100644 contracts/mocks/MockRedemptionManager.sol create mode 100644 contracts/mocks/MockWrongTypeFactory.sol diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol new file mode 100644 index 000000000..9f506b046 --- /dev/null +++ b/contracts/mocks/MockBurnFactory.sol @@ -0,0 +1,101 @@ +pragma solidity ^0.4.24; + +import "./MockRedemptionManager.sol"; +import "../modules/ModuleFactory.sol"; +import "../libraries/Util.sol"; + +/** + * @title Mock Contract Not fit for production environment + */ + +contract MockBurnFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "Mock"; + title = "Mock Manager"; + description = "MockManager"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /*_data*/) external returns(address) { + if(setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Unable to pay setup cost"); + //Check valid bytes - can only call module init function + MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, address(polyToken)); + emit GenerateModuleFromFactory(address(mockRedemptionManager), getName(), address(this), msg.sender, setupCost, now); + return address(mockRedemptionManager); + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory types = new uint8[](1); + types[0] = 5; + return types; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() external view returns(string) { + return description; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string) { + return title; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Returns the instructions associated with the module + */ + function getInstructions() external view returns(string) { + return "Mock Manager - This is mock in nature"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](4); + availableTags[0] = "Mock"; + return availableTags; + } + +} diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index c4553764f..0b679d152 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -39,6 +39,7 @@ contract MockFactory is ModuleFactory { //Checks that _data is valid (not calling anything it shouldn't) require(Util.getSig(_data) == dummySTO.getInitFunction(), "Invalid initialisation"); require(address(dummySTO).call(_data), "Unsuccessfull initialisation"); + emit GenerateModuleFromFactory(address(dummySTO), getName(), address(this), msg.sender, setupCost, now); return address(dummySTO); } diff --git a/contracts/mocks/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol new file mode 100644 index 000000000..5ee50dd19 --- /dev/null +++ b/contracts/mocks/MockRedemptionManager.sol @@ -0,0 +1,75 @@ +pragma solidity ^0.4.24; + +import "../modules/Burn/IBurn.sol"; +import "../modules/Module.sol"; +import "../interfaces/ISecurityToken.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Burn module for burning tokens and keeping track of burnt amounts + */ +contract MockRedemptionManager is IBurn, Module { + using SafeMath for uint256; + + mapping (address => uint256) redeemedTokens; + mapping (address => uint256) tokenToRedeem; + + event Redeemed(address _investor, uint256 _value, uint256 _timestamp); + event RedeemedTokenByOwner(address _investor, address _byWhoom, uint256 _value, uint256 _timestamp); + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) public + Module(_securityToken, _polyAddress) + { + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + /** + * @notice Redeem tokens and track redemptions + * @param _value The number of tokens to redeem + */ + function redeemTokens(uint256 _value) public { + ISecurityToken(securityToken).burnFromWithData(msg.sender, _value, ""); + redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); + emit Redeemed(msg.sender, _value, now); + } + + /** + * @notice Transfer tokens to Module to burn + * @param _value The number of tokens to redeem + */ + function transferToRedeem(uint256 _value) public { + require(ISecurityToken(securityToken).transferFrom(msg.sender, address(this), _value), "Insufficient funds"); + tokenToRedeem[msg.sender] = _value; + } + + /** + * @notice use to redeem tokens by the module + * @param _value The number of tokens to redeem + */ + function redeemTokenByOwner(uint256 _value) public { + require(tokenToRedeem[msg.sender] >= _value); + tokenToRedeem[msg.sender] = tokenToRedeem[msg.sender].sub(_value); + redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); + ISecurityToken(securityToken).burnWithData(_value, ""); + emit RedeemedTokenByOwner(msg.sender, address(this), _value, now); + } + + /** + * @notice Return the permissions flag that are associated with CountTransferManager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](0); + return allPermissions; + } +} diff --git a/contracts/mocks/MockWrongTypeFactory.sol b/contracts/mocks/MockWrongTypeFactory.sol new file mode 100644 index 000000000..4b5cc4c62 --- /dev/null +++ b/contracts/mocks/MockWrongTypeFactory.sol @@ -0,0 +1,101 @@ +pragma solidity ^0.4.24; + +import "./MockRedemptionManager.sol"; +import "../modules/ModuleFactory.sol"; +import "../libraries/Util.sol"; + +/** + * @title Mock Contract Not fit for production environment + */ + +contract MockWrongTypeFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "Mock"; + title = "Mock Manager"; + description = "MockManager"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /*_data*/) external returns(address) { + if(setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Unable to pay setup cost"); + //Check valid bytes - can only call module init function + MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, address(polyToken)); + emit GenerateModuleFromFactory(address(mockRedemptionManager), getName(), address(this), msg.sender, setupCost, now); + return address(mockRedemptionManager); + } + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory types = new uint8[](1); + types[0] = 4; + return types; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() external view returns(string) { + return description; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string) { + return title; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Returns the instructions associated with the module + */ + function getInstructions() external view returns(string) { + return "Mock Manager - This is mock in nature"; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() external view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](4); + availableTags[0] = "Mock"; + return availableTags; + } + +} diff --git a/contracts/modules/Burn/TrackedRedemption.sol b/contracts/modules/Burn/TrackedRedemption.sol index f6211a140..60745f778 100644 --- a/contracts/modules/Burn/TrackedRedemption.sol +++ b/contracts/modules/Burn/TrackedRedemption.sol @@ -41,7 +41,7 @@ contract TrackedRedemption is IBurn, Module { redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); emit Redeemed(msg.sender, _value, now); } - + /** * @notice Return the permissions flag that are associated with CountTransferManager */ diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index de38c2f28..6db725c74 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -275,6 +275,7 @@ contract("CountTransferManager", accounts => { }) it("Should fail to buy some more tokens (more than 2 holders)", async () => { + await I_CountTransferManager.unpause({from: account_issuer }); // Add the Investor in to the whitelist let tx = await I_GeneralTransferManager.modifyWhitelist( account_investor3, diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index 82a77e42a..f72ab54e3 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -27,6 +27,8 @@ const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PolyToken = artifacts.require("./PolyToken.sol"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); +const MockBurnFactory = artifacts.require("./MockBurnFactory.sol"); +const MockWrongTypeFactory = artifacts.require("./MockWrongTypeFactory.sol"); const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -35,6 +37,8 @@ const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); let I_USDTieredSTOProxyFactory; let I_USDTieredSTOFactory; let I_TrackedRedemptionFactory; +let I_MockBurnFactory; +let I_MockWrongTypeBurnFactory; let I_SingleTradeVolumeRestrictionManagerFactory; let I_ManualApprovalTransferManagerFactory; let I_VolumeRestrictionTransferManagerFactory; @@ -378,7 +382,31 @@ export async function deployRedemptionAndVerifyed(accountPolymath, MRProxyInstan } +export async function deployMockRedemptionAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_MockBurnFactory = await MockBurnFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + assert.notEqual( + I_MockBurnFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "MockBurnfactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_MockBurnFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_MockBurnFactory); +} + +export async function deployMockWrongTypeRedemptionAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_MockWrongTypeBurnFactory = await MockWrongTypeFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + + assert.notEqual( + I_MockWrongTypeBurnFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "MockWrongTypeBurnFactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_MockWrongTypeBurnFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_MockWrongTypeBurnFactory); +} diff --git a/test/o_security_token.js b/test/o_security_token.js index 6ea14c5b3..619b80035 100644 --- a/test/o_security_token.js +++ b/test/o_security_token.js @@ -3,13 +3,20 @@ import { duration, ensureException, promisifyLogWatch, latestBlock } from "./hel import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; -import { setUpPolymathNetwork, deployGPMAndVerifyed, deployCappedSTOAndVerifyed } from "./helpers/createInstances"; +import { + setUpPolymathNetwork, + deployGPMAndVerifyed, + deployCappedSTOAndVerifyed, + deployMockRedemptionAndVerifyed, + deployMockWrongTypeRedemptionAndVerifyed + } from "./helpers/createInstances"; const CappedSTOFactory = artifacts.require("./CappedSTOFactory.sol"); const CappedSTO = artifacts.require("./CappedSTO.sol"); const SecurityToken = artifacts.require("./SecurityToken.sol"); const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const MockRedemptionManager = artifacts.require("./MockRedemptionManager.sol"); const Web3 = require("web3"); const BigNumber = require("bignumber.js"); @@ -58,6 +65,9 @@ contract("SecurityToken", accounts => { let I_CappedSTO; let I_PolyToken; let I_PolymathRegistry; + let I_MockRedemptionManagerFactory; + let I_MockRedemptionManager; + // SecurityToken Details (Launched ST on the behalf of the issuer) const name = "Demo Token"; @@ -69,6 +79,7 @@ contract("SecurityToken", accounts => { const permissionManagerKey = 1; const transferManagerKey = 2; const stoKey = 3; + const burnKey = 5; const budget = 0; // Initial fee for ticker registry and security token registry @@ -377,9 +388,37 @@ contract("SecurityToken", accounts => { let tx = await I_SecurityToken.removeModule(I_GeneralTransferManager.address, { from: token_owner }); assert.equal(tx.logs[0].args._types[0], transferManagerKey); assert.equal(tx.logs[0].args._module, I_GeneralTransferManager.address); + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("500"), {from: token_owner}); + await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("200"), {from: account_investor1 }); + assert.equal((await I_SecurityToken.balanceOf(account_investor2)).dividedBy(new BigNumber(10).pow(18)).toNumber(), 200); await revertToSnapshot(key); }); + it("Should successfully remove the module from the middle of the names mapping", async() => { + let snap_Id = await takeSnapshot(); + let D_GPM, D_GPM_1, D_GPM_2; + let FactoryInstances; + let GPMAddress = new Array(); + + [D_GPM] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [D_GPM_1] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + [D_GPM_2] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + FactoryInstances = [D_GPM, D_GPM_1, D_GPM_2]; + // Adding module in the ST + for (let i = 0; i < FactoryInstances.length; i++) { + let tx = await I_SecurityToken.addModule(FactoryInstances[i].address, "", 0, 0, {from: token_owner }); + assert.equal(tx.logs[2].args._types[0], permissionManagerKey, "fail in adding the GPM") + GPMAddress.push(tx.logs[2].args._module); + } + // Archive the one of the module + await I_SecurityToken.archiveModule(GPMAddress[0], {from: token_owner}); + // Remove the module + let tx = await I_SecurityToken.removeModule(GPMAddress[0], {from: token_owner}); + assert.equal(tx.logs[0].args._types[0], permissionManagerKey); + assert.equal(tx.logs[0].args._module, GPMAddress[0]); + await revertToSnapshot(snap_Id); + }); + it("Should successfully archive the module first and fail during achiving the module again", async() => { let key = await takeSnapshot(); await I_SecurityToken.archiveModule(I_GeneralTransferManager.address, { from: token_owner }); @@ -451,6 +490,19 @@ contract("SecurityToken", accounts => { assert.equal(tx.logs[1].args._module, I_CappedSTO.address); assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 100); }); + + it("Should change the budget of the module (decrease it)", async() => { + let tx = await I_SecurityToken.changeModuleBudget(I_CappedSTO.address, 50 * Math.pow(10, 18), { from: token_owner }); + assert.equal(tx.logs[1].args._moduleTypes[0], stoKey); + assert.equal(tx.logs[1].args._module, I_CappedSTO.address); + assert.equal(tx.logs[1].args._budget.dividedBy(new BigNumber(10).pow(18)).toNumber(), 50); + }); + + it("Should fail to get the total supply -- because checkpoint id is greater than present", async() => { + await catchRevert( + I_SecurityToken.totalSupplyAt.call(50) + ); + }) }); describe("General Transfer manager Related test cases", async () => { @@ -824,7 +876,87 @@ contract("SecurityToken", accounts => { }); }); + describe("Test cases for the Mock TrackedRedeemption", async() => { + + it("Should add the tracked redeemption module successfully", async() => { + [I_MockRedemptionManagerFactory] = await deployMockRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); + assert.equal(tx.logs[2].args._types[0], burnKey, "fail in adding the burn manager"); + I_MockRedemptionManager = MockRedemptionManager.at(tx.logs[2].args._module); + // adding the burn module into the GTM + tx = await I_GeneralTransferManager.modifyWhitelist( + I_MockRedemptionManager.address, + latestTime(), + latestTime() + duration.seconds(2), + latestTime() + duration.days(50), + true, + { + from: account_delegate, + gas: 6000000 + } + ); + assert.equal(tx.logs[0].args._investor, I_MockRedemptionManager.address, "Failed in adding the investor in whitelist"); + }); + + it("Should successfully burn tokens", async() => { + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(false, {from: token_owner}); + // Minting some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("1000"), {from: token_owner}); + // Provide approval to trnafer the tokens to Module + await I_SecurityToken.approve(I_MockRedemptionManager.address, web3.utils.toWei("500"), {from: account_investor1}); + // Allow all whitelist transfer + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from: token_owner}); + // Transfer the tokens to module (Burn) + await I_MockRedemptionManager.transferToRedeem(web3.utils.toWei("500"), { from: account_investor1}); + // Redeem tokens + let tx = await I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}); + assert.equal(tx.logs[0].args._investor, account_investor1, "Burn tokens of wrong owner"); + assert.equal((tx.logs[0].args._value).dividedBy(new BigNumber(10).pow(18)).toNumber(), 250); + }); + + it("Should fail to burn the tokens because module get archived", async() => { + await I_SecurityToken.archiveModule(I_MockRedemptionManager.address, {from: token_owner}); + await catchRevert( + I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}) + ); + }) + + it("Should successfully fail in calling the burn functions", async() => { + [I_MockRedemptionManagerFactory] = await deployMockWrongTypeRedemptionAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + let tx = await I_SecurityToken.addModule(I_MockRedemptionManagerFactory.address, "", 0, 0, {from: token_owner }); + I_MockRedemptionManager = MockRedemptionManager.at(tx.logs[2].args._module); + + // adding the burn module into the GTM + tx = await I_GeneralTransferManager.modifyWhitelist( + I_MockRedemptionManager.address, + latestTime(), + latestTime() + duration.seconds(2), + latestTime() + duration.days(50), + true, + { + from: account_delegate, + gas: 6000000 + } + ); + assert.equal(tx.logs[0].args._investor, I_MockRedemptionManager.address, "Failed in adding the investor in whitelist"); + // Provide approval to trnafer the tokens to Module + await I_SecurityToken.approve(I_MockRedemptionManager.address, web3.utils.toWei("500"), {from: account_investor1}); + // Transfer the tokens to module (Burn) + await I_MockRedemptionManager.transferToRedeem(web3.utils.toWei("500"), { from: account_investor1}); + + await catchRevert( + // Redeem tokens + I_MockRedemptionManager.redeemTokenByOwner(web3.utils.toWei("250"), {from: account_investor1}) + ); + }); + + }) + describe("Withdraw Poly", async () => { + it("Should successfully withdraw the poly -- failed because of zero address of token", async() => { + await catchRevert(I_SecurityToken.withdrawERC20("0x00000000000000000000000000000000000000000", web3.utils.toWei("20000", "ether"), { from: account_temp })); + }) + it("Should successfully withdraw the poly", async () => { await catchRevert(I_SecurityToken.withdrawERC20(I_PolyToken.address, web3.utils.toWei("20000", "ether"), { from: account_temp })); }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index e7c1d1298..66ab51a8c 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -392,7 +392,7 @@ contract("USDTieredSTO", accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); await catchRevert( - I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }) + I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }) ); }); @@ -416,7 +416,7 @@ contract("USDTieredSTO", accounts => { let bytesSTO = web3.eth.abi.encodeFunctionCall(functionSignature, config); await I_PolyToken.getTokens(web3.utils.toWei("500"), I_SecurityToken.address); - let tx = await I_SecurityToken.addModule(I_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }); + let tx = await I_SecurityToken.addModule(P_USDTieredSTOFactory.address, bytesSTO, web3.utils.toWei("500"), 0, { from: ISSUER, gasPrice: GAS_PRICE }); await revertToSnapshot(snapId); }); diff --git a/test/x_single_trade_volume_restriction.js b/test/x_single_trade_volume_restriction.js index 34dc130dc..a0e1fb3f0 100644 --- a/test/x_single_trade_volume_restriction.js +++ b/test/x_single_trade_volume_restriction.js @@ -219,15 +219,6 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { ); }); - it("Should allow the primary issuance", async() => { - let snapId = await takeSnapshot(); - await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}); - await catchRevert( - I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}) - ) - await revertToSnapshot(snapId); - }) - it("Should successfully attach the Paid SingleTradeVolumeRestrictionManager with the security token", async () => { let managerArgs = encodeModuleCall(STVRParameters, [false, 90, false]); await I_PolyToken.transfer(I_SecurityToken.address, web3.utils.toWei("500", "ether"), { from: token_owner }); @@ -286,6 +277,15 @@ contract('SingleTradeVolumeRestrictionManager', accounts => { ); }); + it("Should allow the primary issuance", async() => { + let snapId = await takeSnapshot(); + await I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}); + await catchRevert( + I_SingleTradeVolumeRestrictionManager.setAllowPrimaryIssuance(true, {from: token_owner}) + ) + await revertToSnapshot(snapId); + }) + it("add exempt wallet -- Not authorised ", async () => { await catchRevert ( I_SingleTradeVolumeRestrictionManager.addExemptWallet(accounts[5]) From 00811ae95a49bae23579ab66e2b18719543d4888 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 16 Oct 2018 14:04:06 +0530 Subject: [PATCH 4/6] introduced withdrawERC20() in the changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a4896b14..8e38d1048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,11 +26,12 @@ All notable changes to this project will be documented in this file. * Add `getReputationOfFactory()` & `getModuleListOfType()` functions to get the array type data from the ModuleRegistry contract. * Add `_setupCost` in `LogGenerateModuleFromFactory` event. * Add new function `getAllModulesByName()`, To get the list of modules having the same name. #198. -* Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 +* Add new function `modifyTickerDetails()`, To modify the details of undeployed ticker. #230 ## Fixed * Generalize the STO varaible names and added them in `ISTO.sol` to use the common standard in all STOs. -* Generalize the event when any new token get registered with the polymath ecosystem. `LogNewSecurityToken` should emit _ticker, _name, _securityTokenAddress, _owner, _addedAt, _registrant respectively. #230 +* Generalize the event when any new token get registered with the polymath ecosystem. `LogNewSecurityToken` should emit _ticker, _name, _securityTokenAddress, _owner, _addedAt, _registrant respectively. #230 +* Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. ## Removed * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 From 834dd4cd948c696449a385f14534e29ffbf2c536 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 16 Oct 2018 14:04:41 +0530 Subject: [PATCH 5/6] fix --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e38d1048..c4b8fdb42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ All notable changes to this project will be documented in this file. ## Fixed * Generalize the STO varaible names and added them in `ISTO.sol` to use the common standard in all STOs. * Generalize the event when any new token get registered with the polymath ecosystem. `LogNewSecurityToken` should emit _ticker, _name, _securityTokenAddress, _owner, _addedAt, _registrant respectively. #230 -* Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. +* Change the function name of `withdraPoly` to `withdrawERC20` and make the function generalize to extract tokens from the ST contract. parmeters are contract address and the value need to extract from the securityToken. ## Removed * Remove `swarmHash` from the `registerTicker(), addCustomTicker(), generateSecurityToken(), addCustomSecurityToken()` functions of TickerRegistry.sol and SecurityTokenRegistry.sol. #230 From 08dba49edc105ad732f113453bcba47785268b83 Mon Sep 17 00:00:00 2001 From: satyam Date: Tue, 16 Oct 2018 15:35:19 +0530 Subject: [PATCH 6/6] minor fixes --- contracts/SecurityTokenRegistry.sol | 2 +- contracts/mocks/MockBurnFactory.sol | 73 +------------------- contracts/mocks/MockFactory.sol | 81 +---------------------- contracts/mocks/MockRedemptionManager.sol | 40 ++--------- contracts/mocks/MockWrongTypeFactory.sol | 76 +-------------------- contracts/mocks/TestSTOFactory.sol | 68 +------------------ test/b_capped_sto.js | 9 +-- test/i_Issuance.js | 3 +- test/k_module_registry.js | 11 +-- test/m_presale_sto.js | 3 +- test/n_security_token_registry.js | 29 ++++---- test/p_usd_tiered_sto.js | 9 +-- test/s_v130_to_v140_upgrade.js | 13 ++-- test/u_module_registry_proxy.js | 8 +-- 14 files changed, 64 insertions(+), 361 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 7385314fc..29ed14a8a 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -669,7 +669,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _patch Patch version of the proxy */ function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { - require(_STFactoryAddress != address(0)); + require(_STFactoryAddress != address(0), "0x address is not allowed"); _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); } diff --git a/contracts/mocks/MockBurnFactory.sol b/contracts/mocks/MockBurnFactory.sol index 9f506b046..c21b474f1 100644 --- a/contracts/mocks/MockBurnFactory.sol +++ b/contracts/mocks/MockBurnFactory.sol @@ -1,28 +1,21 @@ pragma solidity ^0.4.24; import "./MockRedemptionManager.sol"; -import "../modules/ModuleFactory.sol"; -import "../libraries/Util.sol"; +import "../modules/Burn/TrackedRedemptionFactory.sol"; /** * @title Mock Contract Not fit for production environment */ -contract MockBurnFactory is ModuleFactory { +contract MockBurnFactory is TrackedRedemptionFactory { /** * @notice Constructor * @param _polyAddress Address of the polytoken */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + TrackedRedemptionFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; - name = "Mock"; - title = "Mock Manager"; - description = "MockManager"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } /** @@ -38,64 +31,4 @@ contract MockBurnFactory is ModuleFactory { return address(mockRedemptionManager); } - /** - * @notice Type of the Module factory - */ - function getTypes() external view returns(uint8[]) { - uint8[] memory types = new uint8[](1); - types[0] = 5; - return types; - } - - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - - /** - * @notice Returns the instructions associated with the module - */ - function getInstructions() external view returns(string) { - return "Mock Manager - This is mock in nature"; - } - - /** - * @notice Get the tags related to the module factory - */ - function getTags() external view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](4); - availableTags[0] = "Mock"; - return availableTags; - } - } diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 0b679d152..627efb71c 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -1,14 +1,12 @@ pragma solidity ^0.4.24; -import "../modules/STO/DummySTO.sol"; -import "../modules/ModuleFactory.sol"; -import "../libraries/Util.sol"; +import "../modules/STO/DummySTOFactory.sol"; /** * @title Mock Contract Not fit for production environment */ -contract MockFactory is ModuleFactory { +contract MockFactory is DummySTOFactory { bool public switchTypes = false; /** @@ -16,31 +14,9 @@ contract MockFactory is ModuleFactory { * @param _polyAddress Address of the polytoken */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + DummySTOFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; - name = "Mock"; - title = "Mock Manager"; - description = "MockManager"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - } - /** - * @notice used to launch the Module with the help of factory - * @param _data Data used for the intialization of the module factory variables - * @return address Contract address of the Module - */ - function deploy(bytes _data) external returns(address) { - if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Unable to pay setup cost"); - //Check valid bytes - can only call module init function - DummySTO dummySTO = new DummySTO(msg.sender, address(polyToken)); - //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == dummySTO.getInitFunction(), "Invalid initialisation"); - require(address(dummySTO).call(_data), "Unsuccessfull initialisation"); - emit GenerateModuleFromFactory(address(dummySTO), getName(), address(this), msg.sender, setupCost, now); - return address(dummySTO); } /** @@ -59,57 +35,6 @@ contract MockFactory is ModuleFactory { } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - - /** - * @notice Returns the instructions associated with the module - */ - function getInstructions() external view returns(string) { - return "Mock Manager - This is mock in nature"; - } - - /** - * @notice Get the tags related to the module factory - */ - function getTags() external view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](4); - availableTags[0] = "Mock"; - return availableTags; - } - function changeTypes() external onlyOwner { switchTypes = !switchTypes; } diff --git a/contracts/mocks/MockRedemptionManager.sol b/contracts/mocks/MockRedemptionManager.sol index 5ee50dd19..a2a0a6f7c 100644 --- a/contracts/mocks/MockRedemptionManager.sol +++ b/contracts/mocks/MockRedemptionManager.sol @@ -1,20 +1,14 @@ pragma solidity ^0.4.24; -import "../modules/Burn/IBurn.sol"; -import "../modules/Module.sol"; -import "../interfaces/ISecurityToken.sol"; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; +import "../modules/Burn/TrackedRedemption.sol"; /** * @title Burn module for burning tokens and keeping track of burnt amounts */ -contract MockRedemptionManager is IBurn, Module { - using SafeMath for uint256; - - mapping (address => uint256) redeemedTokens; +contract MockRedemptionManager is TrackedRedemption { + mapping (address => uint256) tokenToRedeem; - event Redeemed(address _investor, uint256 _value, uint256 _timestamp); event RedeemedTokenByOwner(address _investor, address _byWhoom, uint256 _value, uint256 _timestamp); /** @@ -23,27 +17,10 @@ contract MockRedemptionManager is IBurn, Module { * @param _polyAddress Address of the polytoken */ constructor (address _securityToken, address _polyAddress) public - Module(_securityToken, _polyAddress) + TrackedRedemption(_securityToken, _polyAddress) { } - /** - * @notice This function returns the signature of configure function - */ - function getInitFunction() public pure returns (bytes4) { - return bytes4(0); - } - - /** - * @notice Redeem tokens and track redemptions - * @param _value The number of tokens to redeem - */ - function redeemTokens(uint256 _value) public { - ISecurityToken(securityToken).burnFromWithData(msg.sender, _value, ""); - redeemedTokens[msg.sender] = redeemedTokens[msg.sender].add(_value); - emit Redeemed(msg.sender, _value, now); - } - /** * @notice Transfer tokens to Module to burn * @param _value The number of tokens to redeem @@ -64,12 +41,5 @@ contract MockRedemptionManager is IBurn, Module { ISecurityToken(securityToken).burnWithData(_value, ""); emit RedeemedTokenByOwner(msg.sender, address(this), _value, now); } - - /** - * @notice Return the permissions flag that are associated with CountTransferManager - */ - function getPermissions() public view returns(bytes32[]) { - bytes32[] memory allPermissions = new bytes32[](0); - return allPermissions; - } + } diff --git a/contracts/mocks/MockWrongTypeFactory.sol b/contracts/mocks/MockWrongTypeFactory.sol index 4b5cc4c62..f04a3a2de 100644 --- a/contracts/mocks/MockWrongTypeFactory.sol +++ b/contracts/mocks/MockWrongTypeFactory.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./MockRedemptionManager.sol"; +import "./MockBurnFactory.sol"; import "../modules/ModuleFactory.sol"; import "../libraries/Util.sol"; @@ -8,34 +8,15 @@ import "../libraries/Util.sol"; * @title Mock Contract Not fit for production environment */ -contract MockWrongTypeFactory is ModuleFactory { +contract MockWrongTypeFactory is MockBurnFactory { /** * @notice Constructor * @param _polyAddress Address of the polytoken */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + MockBurnFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; - name = "Mock"; - title = "Mock Manager"; - description = "MockManager"; - compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); - } - - /** - * @notice used to launch the Module with the help of factory - * @return address Contract address of the Module - */ - function deploy(bytes /*_data*/) external returns(address) { - if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Unable to pay setup cost"); - //Check valid bytes - can only call module init function - MockRedemptionManager mockRedemptionManager = new MockRedemptionManager(msg.sender, address(polyToken)); - emit GenerateModuleFromFactory(address(mockRedemptionManager), getName(), address(this), msg.sender, setupCost, now); - return address(mockRedemptionManager); } /** @@ -47,55 +28,4 @@ contract MockWrongTypeFactory is ModuleFactory { return types; } - /** - * @notice Get the name of the Module - */ - function getName() public view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - - /** - * @notice Returns the instructions associated with the module - */ - function getInstructions() external view returns(string) { - return "Mock Manager - This is mock in nature"; - } - - /** - * @notice Get the tags related to the module factory - */ - function getTags() external view returns(bytes32[]) { - bytes32[] memory availableTags = new bytes32[](4); - availableTags[0] = "Mock"; - return availableTags; - } - } diff --git a/contracts/mocks/TestSTOFactory.sol b/contracts/mocks/TestSTOFactory.sol index 85c32f2f9..eb26bd922 100644 --- a/contracts/mocks/TestSTOFactory.sol +++ b/contracts/mocks/TestSTOFactory.sol @@ -1,17 +1,15 @@ pragma solidity ^0.4.24; -import "../modules/STO/DummySTO.sol"; -import "../modules/ModuleFactory.sol"; -import "../libraries/Util.sol"; +import "../modules/STO/DummySTOFactory.sol"; -contract TestSTOFactory is ModuleFactory { +contract TestSTOFactory is DummySTOFactory { /** * @notice Constructor * @param _polyAddress Address of the polytoken */ constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public - ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + DummySTOFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { version = "1.0.0"; name = "TestSTO"; @@ -21,66 +19,6 @@ contract TestSTOFactory is ModuleFactory { compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); } - /** - * @notice used to launch the Module with the help of factory - * @param _data Data used for the intialization of the module factory variables - * @return address Contract address of the Module - */ - function deploy(bytes _data) external returns(address) { - if(setupCost > 0) - require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); - //Check valid bytes - can only call module init function - DummySTO dummySTO = new DummySTO(msg.sender, address(polyToken)); - //Checks that _data is valid (not calling anything it shouldn't) - require(Util.getSig(_data) == dummySTO.getInitFunction(), "Provided data is not valid"); - require(address(dummySTO).call(_data), "Un-successfull call"); - return address(dummySTO); - } - - /** - * @notice Type of the Module factory - */ - function getTypes() external view returns(uint8[]) { - uint8[] memory res = new uint8[](1); - res[0] = 3; - return res; - } - - /** - * @notice Get the name of the Module - */ - function getName() external view returns(bytes32) { - return name; - } - - /** - * @notice Get the description of the Module - */ - function getDescription() external view returns(string) { - return description; - } - - /** - * @notice Get the title of the Module - */ - function getTitle() external view returns(string) { - return title; - } - - /** - * @notice Get the version of the Module - */ - function getVersion() external view returns(string) { - return version; - } - - /** - * @notice Get the setup cost of the module - */ - function getSetupCost() external view returns (uint256) { - return setupCost; - } - /** * @notice Returns the instructions associated with the module */ diff --git a/test/b_capped_sto.js b/test/b_capped_sto.js index e1a9b6c13..ff80f1025 100644 --- a/test/b_capped_sto.js +++ b/test/b_capped_sto.js @@ -88,6 +88,7 @@ contract("CappedSTO", accounts => { const cap = web3.utils.toWei("10000"); const rate = 1000; const E_fundRaiseType = 0; + const address_zero = "0x0000000000000000000000000000000000000000"; let startTime_POLY1; let endTime_POLY1; @@ -136,7 +137,7 @@ contract("CappedSTO", accounts => { assert.notEqual( I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "CappedSTOFactory contract was not deployed" ); @@ -197,7 +198,7 @@ contract("CappedSTO", accounts => { it("Should mint the tokens before attaching the STO", async () => { await catchRevert( - I_SecurityToken_ETH.mint("0x0000000000000000000000000000000000000000", web3.utils.toWei("1"), { from: token_owner }) + I_SecurityToken_ETH.mint(address_zero, web3.utils.toWei("1"), { from: token_owner }) ); }); @@ -225,7 +226,7 @@ contract("CappedSTO", accounts => { let startTime = latestTime() + duration.days(1); let endTime = startTime + duration.days(30); - let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], "0x0000000000000000000000000000000000000000"]); + let bytesSTO = encodeModuleCall(STOParameters, [startTime, endTime, cap, rate, [E_fundRaiseType], address_zero]); await catchRevert(I_SecurityToken_ETH.addModule(I_CappedSTOFactory.address, bytesSTO, maxCost, 0, { from: token_owner })); }); @@ -494,7 +495,7 @@ contract("CappedSTO", accounts => { await I_PolyToken.getTokens(value, account_investor1); await I_PolyToken.transfer(I_CappedSTO_Array_ETH[0].address, value, { from: account_investor1 }); - await catchRevert(I_CappedSTO_Array_ETH[0].reclaimERC20("0x0000000000000000000000000000000000000000", { from: token_owner })); + await catchRevert(I_CappedSTO_Array_ETH[0].reclaimERC20(address_zero, { from: token_owner })); }); it("Should successfully reclaim POLY", async () => { diff --git a/test/i_Issuance.js b/test/i_Issuance.js index 2087e2bbe..ac1fcdd37 100644 --- a/test/i_Issuance.js +++ b/test/i_Issuance.js @@ -63,6 +63,7 @@ contract("Issuance", accounts => { const transferManagerKey = 2; const stoKey = 3; const budget = 0; + const address_zero = "0x0000000000000000000000000000000000000000"; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -171,7 +172,7 @@ contract("Issuance", accounts => { assert.notEqual( I_CappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "CappedSTOFactory contract was not deployed" ); diff --git a/test/k_module_registry.js b/test/k_module_registry.js index 9e061612a..193c53bad 100644 --- a/test/k_module_registry.js +++ b/test/k_module_registry.js @@ -75,6 +75,7 @@ contract("ModuleRegistry", accounts => { const transferManagerKey = 2; const stoKey = 3; const budget = 0; + const address_zero = "0x0000000000000000000000000000000000000000"; // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -141,7 +142,7 @@ contract("ModuleRegistry", accounts => { describe("Test the initialize the function", async () => { it("Should successfully update the implementation address -- fail because polymathRegistry address is 0x", async () => { let bytesProxy = encodeProxyCall(MRProxyParameters, [ - "0x0000000000000000000000000000000000000000", + address_zero, account_polymath ]); catchRevert( @@ -155,7 +156,7 @@ contract("ModuleRegistry", accounts => { it("Should successfully update the implementation address -- fail because owner address is 0x", async () => { let bytesProxy = encodeProxyCall(MRProxyParameters, [ I_PolymathRegistry.address, - "0x0000000000000000000000000000000000000000" + address_zero ]); catchRevert( I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { @@ -167,8 +168,8 @@ contract("ModuleRegistry", accounts => { it("Should successfully update the implementation address -- fail because all params are 0x", async () => { let bytesProxy = encodeProxyCall(MRProxyParameters, [ - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000" + address_zero, + address_zero ]); catchRevert( I_ModuleRegistryProxy.upgradeToAndCall("1.0.0", I_ModuleRegistry.address, bytesProxy, { @@ -326,7 +327,7 @@ contract("ModuleRegistry", accounts => { assert.notEqual( I_CappedSTOFactory2.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "CappedSTOFactory contract was not deployed" ); diff --git a/test/m_presale_sto.js b/test/m_presale_sto.js index 7f7922241..4e2e80327 100644 --- a/test/m_presale_sto.js +++ b/test/m_presale_sto.js @@ -70,6 +70,7 @@ contract("PreSaleSTO", accounts => { // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); let endTime; + const address_zero = "0x0000000000000000000000000000000000000000"; const STOParameters = ["uint256"]; before(async () => { @@ -366,7 +367,7 @@ contract("PreSaleSTO", accounts => { await I_PolyToken.getTokens(value, account_investor1); await I_PolyToken.transfer(I_PreSaleSTO.address, value, { from: account_investor1 }); - await catchRevert(I_PreSaleSTO.reclaimERC20("0x0000000000000000000000000000000000000000", { from: token_owner })); + await catchRevert(I_PreSaleSTO.reclaimERC20(address_zero, { from: token_owner })); }); it("Should successfully reclaim POLY", async () => { diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index f31344214..9000b87ed 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -70,6 +70,7 @@ contract("SecurityTokenRegistry", accounts => { const name2 = "Demo2 Token"; const symbol2 = "DET2"; const tokenDetails2 = "This is equity type of issuance"; + const address_zero = "0x0000000000000000000000000000000000000000"; // Module key const permissionManagerKey = 1; @@ -125,7 +126,7 @@ contract("SecurityTokenRegistry", accounts => { assert.notEqual( I_SecurityTokenRegistry.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "SecurityTokenRegistry contract was not deployed" ); @@ -155,7 +156,7 @@ contract("SecurityTokenRegistry", accounts => { describe("Test the initialize the function", async () => { it("Should successfully update the implementation address -- fail because polymathRegistry address is 0x", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ - "0x0000000000000000000000000000000000000000", + address_zero, I_STFactory.address, initRegFee, initRegFee, @@ -173,7 +174,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully update the implementation address -- fail because STFactory address is 0x", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ I_PolymathRegistry.address, - "0x0000000000000000000000000000000000000000", + address_zero, initRegFee, initRegFee, I_PolyToken.address, @@ -227,7 +228,7 @@ contract("SecurityTokenRegistry", accounts => { I_STFactory.address, initRegFee, initRegFee, - "0x0000000000000000000000000000000000000000", + address_zero, account_polymath ]); catchRevert( @@ -245,7 +246,7 @@ contract("SecurityTokenRegistry", accounts => { initRegFee, initRegFee, I_PolyToken.address, - "0x0000000000000000000000000000000000000000" + address_zero ]); catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { @@ -257,12 +258,12 @@ contract("SecurityTokenRegistry", accounts => { it("Should successfully update the implementation address -- fail because all params get 0", async () => { let bytesProxy = encodeProxyCall(STRProxyParameters, [ - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000", + address_zero, + address_zero, 0, 0, - "0x0000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000" + address_zero, + address_zero ]); catchRevert( I_SecurityTokenRegistryProxy.upgradeToAndCall("1.0.0", I_SecurityTokenRegistry.address, bytesProxy, { @@ -338,7 +339,7 @@ contract("SecurityTokenRegistry", accounts => { await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp }); catchRevert( - I_STRProxied.registerTicker("0x0000000000000000000000000000000000000000", symbol, name, { from: account_temp }), + I_STRProxied.registerTicker(address_zero, symbol, name, { from: account_temp }), "tx revert -> owner should not be 0x" ); }); @@ -447,7 +448,7 @@ contract("SecurityTokenRegistry", accounts => { it("Should get the details of unregistered token", async () => { let tx = await I_STRProxied.getTickerDetails.call("TORO"); - assert.equal(tx[0], "0x0000000000000000000000000000000000000000", "Should be 0x as ticker is not exists in the registry"); + assert.equal(tx[0], address_zero, "Should be 0x as ticker is not exists in the registry"); assert.equal(tx[3], "", "Should be an empty string"); assert.equal(tx[4], false, "Status if the symbol should be undeployed -- false"); }); @@ -461,7 +462,7 @@ contract("SecurityTokenRegistry", accounts => { assert.equal(data[4], false, "Token is not launched yet so it should return False"); data = await I_SecurityTokenRegistry.getTickerDetails(symbol, { from: token_owner }); console.log("This is the data from the original securityTokenRegistry contract"); - assert.equal(data[0], "0x0000000000000000000000000000000000000000", "Token owner should be 0x"); + assert.equal(data[0], address_zero, "Token owner should be 0x"); }); it("Should fail to generate new security token if fee not provided", async () => { @@ -559,7 +560,7 @@ contract("SecurityTokenRegistry", accounts => { assert.notEqual( I_STFactory002.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "STFactory002 contract was not deployed" ); await I_STRProxied.setProtocolVersion(I_STFactory002.address, 0, 2, 0, { from: account_polymath }); @@ -601,7 +602,7 @@ contract("SecurityTokenRegistry", accounts => { I_SecurityTokenRegistryV2 = await SecurityTokenRegistryMock.new({ from: account_polymath }); assert.notEqual( I_SecurityTokenRegistryV2.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "SecurityTokenRegistry contract was not deployed" ); }); diff --git a/test/p_usd_tiered_sto.js b/test/p_usd_tiered_sto.js index 66ab51a8c..62cd4cc05 100644 --- a/test/p_usd_tiered_sto.js +++ b/test/p_usd_tiered_sto.js @@ -70,6 +70,7 @@ contract("USDTieredSTO", accounts => { const TMKEY = 2; const STOKEY = 3; let snapId; + const address_zero = "0x0000000000000000000000000000000000000000"; // Initial fee for ticker registry and security token registry const REGFEE = web3.utils.toWei("250"); @@ -734,7 +735,7 @@ contract("USDTieredSTO", accounts => { it("Should fail because Zero address is not permitted for wallet", async () => { let stoId = 0; - let wallet = "0x0000000000000000000000000000000000000000"; + let wallet = address_zero; let config = [ _startTime[stoId], _endTime[stoId], @@ -757,7 +758,7 @@ contract("USDTieredSTO", accounts => { it("Should fail because Zero address is not permitted for reserveWallet", async () => { let stoId = 0; - let reserveWallet = "0x0000000000000000000000000000000000000000"; + let reserveWallet = address_zero; let config = [ _startTime[stoId], _endTime[stoId], @@ -894,7 +895,7 @@ contract("USDTieredSTO", accounts => { await I_USDTieredSTO_Array[stoId].modifyAddresses( "0x0000000000000000000000000400000000000000", "0x0000000000000000000003000000000000000000", - "0x0000000000000000000000000000000000000000", + address_zero, { from: ISSUER } ); assert.equal( @@ -909,7 +910,7 @@ contract("USDTieredSTO", accounts => { ); assert.equal( await I_USDTieredSTO_Array[stoId].usdToken.call(), - "0x0000000000000000000000000000000000000000", + address_zero, "STO Configuration doesn't set as expected" ); }); diff --git a/test/s_v130_to_v140_upgrade.js b/test/s_v130_to_v140_upgrade.js index 8422dc6ee..3fb3092aa 100644 --- a/test/s_v130_to_v140_upgrade.js +++ b/test/s_v130_to_v140_upgrade.js @@ -33,6 +33,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { // Initial fee for ticker registry and security token registry const REGFEE = web3.utils.toWei("250"); const STOSetupCost = 0; + const address_zero = "0x0000000000000000000000000000000000000000"; // Module key const STOKEY = 3; @@ -187,7 +188,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { console.log(I_POLYOracle.address); assert.notEqual( I_POLYOracle.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "POLYOracle contract was not deployed" ); tx = await I_PolymathRegistry.changeAddress("PolyUsdOracle", I_POLYOracle.address, { from: POLYMATH }); @@ -198,13 +199,13 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { it("Should successfully deploy ETH Oracle and register on PolymathRegistry", async () => { I_USDOracle = await ETHOracle.new( "0x216d678c14be600cb88338e763bb57755ca2b1cf", - "0x0000000000000000000000000000000000000000", + address_zero, "ETH", { from: POLYMATH } ); assert.notEqual( I_USDOracle.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "USDOracle contract was not deployed" ); tx = await I_PolymathRegistry.changeAddress("EthUsdOracle", I_USDOracle.address, { from: POLYMATH }); @@ -227,7 +228,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { ); assert.notEqual( I_USDTieredSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "USDTieredSTOFactory contract was not deployed" ); let setupCost = await I_USDTieredSTOFactory.setupCost({ from: POLYMATH }); @@ -249,7 +250,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { I_UpgradedCappedSTOFactory = await CappedSTOFactory.new(I_PolyToken.address, STOSetupCost, 0, 0, { from: POLYMATH }); assert.notEqual( I_UpgradedCappedSTOFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "CappedSTOFactory contract was not deployed" ); let setupCost = await I_UpgradedCappedSTOFactory.setupCost({ from: POLYMATH }); @@ -281,7 +282,7 @@ contract("Upgrade from v1.3.0 to v1.4.0", accounts => { }); assert.notEqual( I_ManualApprovalTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "ManualApprovalTransferManagerFactory contract was not deployed" ); }); diff --git a/test/u_module_registry_proxy.js b/test/u_module_registry_proxy.js index 4ba4d12c6..6d00b8fe2 100644 --- a/test/u_module_registry_proxy.js +++ b/test/u_module_registry_proxy.js @@ -41,7 +41,7 @@ contract("ModuleRegistryProxy", accounts => { const initRegFee = web3.utils.toWei("250"); const version = "1.0.0"; const message = "Transaction Should Fail!"; - + const address_zero = "0x0000000000000000000000000000000000000000"; // SecurityToken Details for funds raise Type ETH const name = "Team"; const symbol = "SAP"; @@ -128,7 +128,7 @@ contract("ModuleRegistryProxy", accounts => { assert.notEqual( I_GeneralTransferManagerFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "GeneralTransferManagerFactory contract was not deployed" ); @@ -143,7 +143,7 @@ contract("ModuleRegistryProxy", accounts => { assert.notEqual( I_STFactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "STFactory contract was not deployed" ); }); @@ -166,7 +166,7 @@ contract("ModuleRegistryProxy", accounts => { assert.notEqual( I_GeneralPermissionManagerfactory.address.valueOf(), - "0x0000000000000000000000000000000000000000", + address_zero, "GeneralPermissionManagerFactory contract was not deployed" );