diff --git a/contracts/modules/TransferManager/ExchangeTransferManager.sol b/contracts/modules/TransferManager/ExchangeTransferManager.sol index 49a969435..d675e4758 100644 --- a/contracts/modules/TransferManager/ExchangeTransferManager.sol +++ b/contracts/modules/TransferManager/ExchangeTransferManager.sol @@ -23,12 +23,13 @@ contract ExchangeTransferManager is ITransferManager { } function verifyTransfer(address _from, address _to, uint256 /*_amount*/) public view returns(bool) { - if (_from == exchange) { - return getExchangePermission(_to); - } else if (_to == exchange) { - return getExchangePermission(_from); + if (!paused) { + if (_from == exchange) { + return getExchangePermission(_to); + } else if (_to == exchange) { + return getExchangePermission(_from); + } } - return false; } @@ -62,4 +63,5 @@ contract ExchangeTransferManager is ITransferManager { // e.g. calling out to another contract maintained by the exchange to get list of allowed users return whitelist[_investor]; } + } diff --git a/contracts/modules/TransferManager/GeneralTransferManager.sol b/contracts/modules/TransferManager/GeneralTransferManager.sol index 17c9b61ae..58e8768d7 100644 --- a/contracts/modules/TransferManager/GeneralTransferManager.sol +++ b/contracts/modules/TransferManager/GeneralTransferManager.sol @@ -101,20 +101,23 @@ contract GeneralTransferManager is ITransferManager { * c) Buyer's purchase lockup is over */ function verifyTransfer(address _from, address _to, uint256 /*_amount*/) public view returns(bool) { - if (allowAllTransfers) { + if (!paused) { + if (allowAllTransfers) { //All transfers allowed, regardless of whitelist return true; + } + if (allowAllWhitelistTransfers) { + //Anyone on the whitelist can transfer, regardless of block number + return (onWhitelist(_to) && onWhitelist(_from)); + } + if (allowAllWhitelistIssuances && _from == issuanceAddress) { + return onWhitelist(_to); + } + //Anyone on the whitelist can transfer provided the blocknumber is large enough + return ((onWhitelist(_from) && whitelist[_from].fromTime <= now) && + (onWhitelist(_to) && whitelist[_to].toTime <= now)); } - if (allowAllWhitelistTransfers) { - //Anyone on the whitelist can transfer, regardless of block number - return (onWhitelist(_to) && onWhitelist(_from)); - } - if (allowAllWhitelistIssuances && _from == issuanceAddress) { - return onWhitelist(_to); - } - //Anyone on the whitelist can transfer provided the blocknumber is large enough - return ((onWhitelist(_from) && whitelist[_from].fromTime <= now) && - (onWhitelist(_to) && whitelist[_to].toTime <= now)); + return false; } /** @@ -194,4 +197,9 @@ contract GeneralTransferManager is ITransferManager { return (((whitelist[_investor].fromTime != 0) || (whitelist[_investor].toTime != 0)) && (whitelist[_investor].expiryTime >= now)); } + + // function pauseTransfers(bool _pause) public { + // pause = _pause; + // emit LogTransfersHalted(_pause, now); + // } } diff --git a/contracts/modules/TransferManager/ITransferManager.sol b/contracts/modules/TransferManager/ITransferManager.sol index 3b6ec1ea7..67bf2c3f9 100644 --- a/contracts/modules/TransferManager/ITransferManager.sol +++ b/contracts/modules/TransferManager/ITransferManager.sol @@ -5,6 +5,29 @@ import "../../interfaces/IModule.sol"; contract ITransferManager is IModule { + event Pause(uint256 _timestammp); + event Unpause(uint256 _timestamp); + + bool public paused = false; + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() onlyOwner public { + require(!paused); + paused = true; + emit Pause(now); + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() onlyOwner public { + require(paused); + paused = false; + emit Unpause(now); + } + function verifyTransfer(address _from, address _to, uint256 _amount) public view returns(bool); } diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 15ddb1d99..8d486d081 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -25,7 +25,8 @@ contract SecurityToken is ISecurityToken, StandardToken, DetailedERC20 { using SafeMath for uint256; bytes32 public securityTokenVersion = "0.0.1"; - + // Use to halt all the transactions + bool public freeze = false; // Reference to the POLY token. ERC20 public polyToken; @@ -56,6 +57,7 @@ contract SecurityToken is ISecurityToken, StandardToken, DetailedERC20 { event LogModuleRemoved(uint8 indexed _type, address _module, uint256 _timestamp); event LogModuleBudgetChanged(uint8 indexed _moduleType, address _module, uint256 _budget); event Mint(address indexed to, uint256 amount); + event LogFreezeTransfers(bool _freeze, uint256 _timestamp); //if _fallback is true, then we only allow the module if it is set, if it is not set we only allow the owner modifier onlyModule(uint8 _moduleType, bool _fallback) { @@ -223,6 +225,24 @@ contract SecurityToken is ISecurityToken, StandardToken, DetailedERC20 { granularity = _granularity; } + /** + * @dev freeze all the transfers + */ + function freezeTransfers() public onlyOwner { + require(!freeze); + freeze = true; + emit LogFreezeTransfers(freeze, now); + } + + /** + * @dev un-freeze all the transfers + */ + function unfreezeTransfers() public onlyOwner { + require(freeze); + freeze = false; + emit LogFreezeTransfers(freeze, now); + } + /** * @dev Overloaded version of the transfer function */ @@ -242,13 +262,15 @@ contract SecurityToken is ISecurityToken, StandardToken, DetailedERC20 { // Permissions this to a TransferManager module, which has a key of 2 // If no TransferManager return true function verifyTransfer(address _from, address _to, uint256 _amount) public view checkGranularity(_amount) returns (bool success) { - if (modules[TRANSFERMANAGER_KEY].length == 0) { - return true; - } - for (uint8 i = 0; i < modules[TRANSFERMANAGER_KEY].length; i++) { - if (ITransferManager(modules[TRANSFERMANAGER_KEY][i].moduleAddress).verifyTransfer(_from, _to, _amount)) { + if (!freeze) { + if (modules[TRANSFERMANAGER_KEY].length == 0) { return true; } + for (uint8 i = 0; i < modules[TRANSFERMANAGER_KEY].length; i++) { + if (ITransferManager(modules[TRANSFERMANAGER_KEY][i].moduleAddress).verifyTransfer(_from, _to, _amount)) { + return true; + } + } } return false; } diff --git a/test/Issuance.js b/test/Issuance.js index b7ed96265..ece67a35c 100644 --- a/test/Issuance.js +++ b/test/Issuance.js @@ -235,7 +235,7 @@ contract('Issuance', accounts => { }); it("POLYMATH: Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: account_polymath }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: account_polymath, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); diff --git a/test/capped_sto.js b/test/capped_sto.js index a2e84ea62..5736e147f 100644 --- a/test/capped_sto.js +++ b/test/capped_sto.js @@ -238,7 +238,7 @@ contract('CappedSTO', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); @@ -580,7 +580,7 @@ contract('CappedSTO', accounts => { it("POLY: Should generate the new security token with the same symbol as registered above", async () => { P_startTime = endTime + duration.days(2); P_endTime = P_startTime + duration.days(30); - let tx = await I_SecurityTokenRegistry.generateSecurityToken(P_name, P_symbol, P_decimals, P_tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(P_name, P_symbol, P_decimals, P_tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, P_symbol, "SecurityToken doesn't get deployed"); diff --git a/test/exchange_transfer_manager.js b/test/exchange_transfer_manager.js index f93f55dd5..002823bc6 100644 --- a/test/exchange_transfer_manager.js +++ b/test/exchange_transfer_manager.js @@ -236,7 +236,7 @@ contract('ExchangeTransferManager', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); diff --git a/test/general_transfer_manager.js b/test/general_transfer_manager.js index 7a6b58721..8d5a7fbe0 100644 --- a/test/general_transfer_manager.js +++ b/test/general_transfer_manager.js @@ -229,7 +229,7 @@ contract('GeneralTransferManager', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas: 5000000}); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); @@ -496,6 +496,20 @@ contract('GeneralTransferManager', accounts => { }); + it("should failed in trasfering the tokens", async() => { + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); + await I_GeneralTransferManager.pause({from: token_owner}); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('2','ether'), {from: account_investor2}); + } catch(error) { + console.log(`Failed because trasfer is paused`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + }); }); diff --git a/test/module_registry.js b/test/module_registry.js index eafd8fa28..27909574b 100644 --- a/test/module_registry.js +++ b/test/module_registry.js @@ -372,7 +372,7 @@ contract('ModuleRegistry', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); diff --git a/test/presale_sto.js b/test/presale_sto.js index 255293d2a..1bbc3dbe0 100644 --- a/test/presale_sto.js +++ b/test/presale_sto.js @@ -209,7 +209,7 @@ contract('PreSaleSTO', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); diff --git a/test/security_token.js b/test/security_token.js index dee17040c..4f4255532 100644 --- a/test/security_token.js +++ b/test/security_token.js @@ -241,7 +241,7 @@ contract('SecurityToken', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); @@ -625,6 +625,65 @@ contract('SecurityToken', accounts => { assert.ok(errorThrown, message); }); + it("Should freeze the transfers", async() => { + let tx = await I_SecurityToken.freezeTransfers({from: token_owner}); + assert.isTrue(tx.logs[0].args._freeze); + }); + + it("Should fail in buying to tokens", async() => { + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_temp, + fromTime, + toTime, + expiryTime, + { + from: account_delegate, + gas: 500000 + }); + + assert.equal(tx.logs[0].args._investor, account_temp, "Failed in adding the investor in whitelist"); + + let errorThrown = false; + try { + // Fallback transaction + await web3.eth.sendTransaction({ + from: account_temp, + to: I_CappedSTO.address, + gas: 210000, + value: web3.utils.toWei('1', 'ether') + }); + + } catch (error) { + console.log(`Because all transfers get freezed`); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should fail in trasfering the tokens from one user to another", async() => { + await I_GeneralTransferManager.changeAllowAllWhitelistTransfers(true, {from : token_owner}); + console.log(await I_SecurityToken.balanceOf(account_investor1)); + let errorThrown = false; + try { + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); + } catch(error) { + console.log('failed in trasfer because all transfers are at hold'); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + }); + + it("Should un freeze all the transfers", async() => { + let tx = await I_SecurityToken.unfreezeTransfers({from: token_owner}); + assert.isFalse(tx.logs[0].args._freeze); + }); + + it("Should able to transfers the tokens from one user to another", async() => { + console.log(await I_SecurityToken.balanceOf(account_investor1)); + await I_SecurityToken.transfer(account_investor1, web3.utils.toWei('1', 'ether'), {from: account_temp}); + }); }); }); \ No newline at end of file diff --git a/test/security_token_registry.js b/test/security_token_registry.js index fad292b35..8797b670e 100644 --- a/test/security_token_registry.js +++ b/test/security_token_registry.js @@ -233,7 +233,7 @@ contract('SecurityTokenRegistry', accounts => { }); it("Should generate the new security token with the same symbol as registered above", async () => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name, symbol, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol, "SecurityToken doesn't get deployed"); @@ -281,7 +281,7 @@ contract('SecurityTokenRegistry', accounts => { }); it("Should generate the new security token with version 2", async() => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name2, symbol2, decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name2, symbol2, decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, symbol2, "SecurityToken doesn't get deployed"); @@ -329,7 +329,7 @@ contract('SecurityTokenRegistry', accounts => { }); it("Should generate the new security token with version 3", async() => { - let tx = await I_SecurityTokenRegistry.generateSecurityToken(name2, "DET3", decimals, tokenDetails, false, { from: token_owner }); + let tx = await I_SecurityTokenRegistry.generateSecurityToken(name2, "DET3", decimals, tokenDetails, false, { from: token_owner, gas:5000000 }); // Verify the successful generation of the security token assert.equal(tx.logs[1].args._ticker, "DET3", "SecurityToken doesn't get deployed");