From dc5657b3b8dc1acbce06adbc882917ce1496fed5 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 29 Nov 2018 12:04:55 +0100 Subject: [PATCH 1/6] fixing audit change request from Mudit --- .../modules/TransferManager/CountTransferManager.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/modules/TransferManager/CountTransferManager.sol b/contracts/modules/TransferManager/CountTransferManager.sol index b54870251..86a537ebe 100644 --- a/contracts/modules/TransferManager/CountTransferManager.sol +++ b/contracts/modules/TransferManager/CountTransferManager.sol @@ -26,12 +26,14 @@ contract CountTransferManager is ITransferManager { } /** @notice Used to verify the transfer transaction and prevent a transfer if it passes the allowed amount of token holders + * @param _from Address of the sender * @param _to Address of the receiver + * @param _amount Amount to send */ function verifyTransfer( - address /* _from */, + address _from, address _to, - uint256 /* _amount */, + uint256 _amount, bytes /* _data */, bool /* _isTransfer */ ) @@ -41,7 +43,7 @@ contract CountTransferManager is ITransferManager { if (!paused) { if (maxHolderCount < ISecurityToken(securityToken).getInvestorCount()) { // Allow transfers to existing maxHolders - if (ISecurityToken(securityToken).balanceOf(_to) != 0) { + if (ISecurityToken(securityToken).balanceOf(_to) != 0 || ISecurityToken(securityToken).balanceOf(_from) == _amount) { return Result.NA; } return Result.INVALID; From 8ab687e0d3f3398545566a38433b73f14f67f77d Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 30 Nov 2018 13:29:03 +0100 Subject: [PATCH 2/6] added test cases for adding new holders and removing one at the same time when it is already full. --- test/d_count_transfer_manager.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 1a1e7717a..9656c45c9 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -339,6 +339,12 @@ contract("CountTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); }); + it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { + console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); + await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); + assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); + }); + it("Should be able to consolidate balances", async () => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); }); From 6bcab54bde9cd089860885804a9a3ebced7cf148 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Fri, 30 Nov 2018 15:34:48 +0100 Subject: [PATCH 3/6] WIP --- test/d_count_transfer_manager.js | 80 ++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 9656c45c9..4a2b0b306 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -40,6 +40,7 @@ contract("CountTransferManager", accounts => { let I_GeneralPermissionManager; let I_CountTransferManager; let I_GeneralTransferManager; + let I_GeneralTransferManager2; let I_ExchangeTransferManager; let I_ModuleRegistry; let I_ModuleRegistryProxy; @@ -49,12 +50,14 @@ contract("CountTransferManager", accounts => { let I_SecurityTokenRegistry; let I_STFactory; let I_SecurityToken; + let I_SecurityToken2; let I_PolyToken; let I_PolymathRegistry; // SecurityToken Details const name = "Team"; const symbol = "sap"; + const symbol2 = "sapp"; const tokenDetails = "This is equity type of issuance"; const decimals = 18; const contact = "team@polymath.network"; @@ -339,11 +342,11 @@ contract("CountTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); }); - it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { - console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); - await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); - assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); - }); + // it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { + // console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); + // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); + // assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); + // }); it("Should be able to consolidate balances", async () => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); @@ -354,6 +357,73 @@ contract("CountTransferManager", accounts => { assert.equal(perm.length, 1); }); + describe("Test cases for adding and removing acc holder at the same time", async () => { + it("deploy a new token & auto attach modules", async () => { + + //register ticker and deploy token + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol2, contact, { from: token_owner }); + + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx2 = await I_STRProxied.generateSecurityToken(name, symbol2, tokenDetails, false, { from: token_owner }); + + I_SecurityToken2 = SecurityToken.at(tx2.logs[1].args._securityTokenAddress); + + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + + it("add 3 holders to the token", async () => { + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor2, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor3, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); + await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); + + assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); + }); + }); + describe("Test cases for the factory", async () => { it("should get the exact details of the factory", async () => { assert.equal(await I_CountTransferManagerFactory.getSetupCost.call(), 0); From 1319a81387ee3bf25d68f74eb678caa64812727e Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 4 Dec 2018 12:07:19 +0100 Subject: [PATCH 4/6] adjust test cases for adding and removing holders at the same time when max holder amount is full --- test/d_count_transfer_manager.js | 45 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 4a2b0b306..303a3b6c0 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -39,6 +39,7 @@ contract("CountTransferManager", accounts => { let I_CountTransferManagerFactory; let I_GeneralPermissionManager; let I_CountTransferManager; + let I_CountTransferManager2; let I_GeneralTransferManager; let I_GeneralTransferManager2; let I_ExchangeTransferManager; @@ -342,12 +343,6 @@ contract("CountTransferManager", accounts => { await catchRevert(I_SecurityToken.transfer(account_investor3, web3.utils.toWei("2", "ether"), { from: account_investor2 })); }); - // it("Should be able to transfer to a new token holder if all tokens are transferred and existing holder is removed", async () => { - // console.log('acc2 balancce is ' + (await I_SecurityToken.balanceOf(account_investor2)).toNumber()); - // await I_SecurityToken.transfer(account_investor3, web3.utils.toWei("4", "ether"), { from: account_investor2 }); - // assert((await I_SecurityToken.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("4", "ether")); - // }); - it("Should be able to consolidate balances", async () => { await I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }); }); @@ -418,10 +413,46 @@ contract("CountTransferManager", accounts => { // Mint some tokens await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); - await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); }); + + // Add count transfer manager and only allow 2 holders + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }) + ); + }); + + it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { + const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); + await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); + console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); + }); + + it("Should allow add a new token holder while transfer all the tokens at one go", async () => { + + let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); + console.log('amount is '+amount); + await I_SecurityToken2.transfer(account_investor3, amount, { from: account_investor2 }); + assert((await I_SecurityToken2.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("2", "ether")); + + }); }); describe("Test cases for the factory", async () => { From a7e6eed6a276ecaa4028e3b83f94ba1063a04630 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 4 Dec 2018 21:58:17 -0500 Subject: [PATCH 5/6] Bump the version --- .../modules/TransferManager/CountTransferManagerFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/CountTransferManagerFactory.sol b/contracts/modules/TransferManager/CountTransferManagerFactory.sol index d9b1328f7..c42cebc61 100644 --- a/contracts/modules/TransferManager/CountTransferManagerFactory.sol +++ b/contracts/modules/TransferManager/CountTransferManagerFactory.sol @@ -16,7 +16,7 @@ contract CountTransferManagerFactory is ModuleFactory { constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) { - version = "1.0.0"; + version = "2.1.0"; name = "CountTransferManager"; title = "Count Transfer Manager"; description = "Restrict the number of investors"; From b8333bfea881a020993f3782061629f8ce20b3f9 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 5 Dec 2018 12:35:30 +0100 Subject: [PATCH 6/6] adjust test logic --- test/d_count_transfer_manager.js | 97 ++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/test/d_count_transfer_manager.js b/test/d_count_transfer_manager.js index 303a3b6c0..c3cfa19e8 100644 --- a/test/d_count_transfer_manager.js +++ b/test/d_count_transfer_manager.js @@ -85,6 +85,7 @@ contract("CountTransferManager", accounts => { account_investor1 = accounts[7]; account_investor2 = accounts[8]; account_investor3 = accounts[9]; + account_investor4 = accounts[6]; // Step 1: Deploy the genral PM ecosystem let instances = await setUpPolymathNetwork(account_polymath, token_owner); @@ -370,8 +371,7 @@ contract("CountTransferManager", accounts => { }); it("add 3 holders to the token", async () => { - - await I_GeneralTransferManager2.modifyWhitelist( + await I_GeneralTransferManager2.modifyWhitelist( account_investor1, latestTime(), latestTime(), @@ -406,53 +406,64 @@ contract("CountTransferManager", accounts => { gas: 500000 } ); - + + await I_GeneralTransferManager2.modifyWhitelist( + account_investor4, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 500000 + } + ); + // Jump time await increaseTime(5000); - // Mint some tokens + // Add 3 holders to the token await I_SecurityToken2.mint(account_investor1, web3.utils.toWei("1", "ether"), { from: token_owner }); await I_SecurityToken2.mint(account_investor2, web3.utils.toWei("1", "ether"), { from: token_owner }); - + await I_SecurityToken2.mint(account_investor3, web3.utils.toWei("1", "ether"), { from: token_owner }); assert.equal((await I_SecurityToken2.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("1", "ether")); - }); - - // Add count transfer manager and only allow 2 holders - it("Should intialize the auto attached modules", async () => { - let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; - I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); - }); - - it("Should successfully attach the CountTransferManager factory with the security token", async () => { - await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); - await catchRevert( - I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { - from: token_owner - }) - ); - }); - - it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { - const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); - assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); - assert.equal( - web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), - "CountTransferManager", - "CountTransferManager module was not added" - ); - I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); - await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); - console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); - }); - - it("Should allow add a new token holder while transfer all the tokens at one go", async () => { - - let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); - console.log('amount is '+amount); - await I_SecurityToken2.transfer(account_investor3, amount, { from: account_investor2 }); - assert((await I_SecurityToken2.balanceOf(account_investor3)).toNumber(), web3.utils.toWei("2", "ether")); - - }); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken2.getModulesByType(2))[0]; + I_GeneralTransferManager2 = GeneralTransferManager.at(moduleData); + }); + + it("Should successfully attach the CountTransferManager factory with the security token", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("500", "ether"), token_owner); + await catchRevert( + I_SecurityToken2.addModule(P_CountTransferManagerFactory.address, bytesSTO, web3.utils.toWei("500", "ether"), 0, { + from: token_owner + }) + ); + }); + + it("Should successfully attach the CountTransferManager with the security token and set max holder to 2", async () => { + const tx = await I_SecurityToken2.addModule(I_CountTransferManagerFactory.address, bytesSTO, 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "CountTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""), + "CountTransferManager", + "CountTransferManager module was not added" + ); + I_CountTransferManager2 = CountTransferManager.at(tx.logs[2].args._module); + await I_CountTransferManager2.changeHolderCount(2, {from: token_owner}); + console.log('current max holder number is '+ await I_CountTransferManager2.maxHolderCount({from: token_owner})); + }); + + it("Should allow add a new token holder while transfer all the tokens at one go", async () => { + let amount = (await I_SecurityToken2.balanceOf(account_investor2)).toNumber(); + let investorCount = await I_SecurityToken2.getInvestorCount({from: account_investor2 }); + console.log("current investor count is " + investorCount); + await I_SecurityToken2.transfer(account_investor4, amount, { from: account_investor2 }); + assert((await I_SecurityToken2.balanceOf(account_investor4)).toNumber(), amount, {from: account_investor2 }); + assert(await I_SecurityToken2.getInvestorCount({from: account_investor2 }), investorCount); + }); }); describe("Test cases for the factory", async () => {