From 23f5f98b8c7ed6c959a89bcb3a5044a45cb7c7bf Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Fri, 28 Sep 2018 19:25:39 +0100 Subject: [PATCH 01/19] Optimisations --- contracts/SecurityTokenRegistry.sol | 211 +++++++++--------- contracts/interfaces/IOwnable.sol | 2 +- .../interfaces/ISecurityTokenRegistry.sol | 2 +- contracts/tokens/SecurityToken.sol | 7 +- 4 files changed, 106 insertions(+), 116 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 1ae6193ff..9ec100df1 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -116,8 +116,8 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPausedOrOwner() { - if (msg.sender == getAddress(Encoder.getKey("owner"))) - _; + if (msg.sender == getAddress(Encoder.getKey("owner"))) + _; else { require(!getBool(Encoder.getKey("paused")), "Already paused"); _; @@ -145,12 +145,6 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { // Initialization ///////////////////////////// - // Constructor - constructor () public - { - - } - /** * @notice initializes instance of STR * @param _polymathRegistry is the address of the Polymath Registry @@ -162,9 +156,8 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function initialize(address _polymathRegistry, address _STFactory, uint256 _stLaunchFee, uint256 _tickerRegFee, address _polyToken, address _owner) payable external { require(!getBool(Encoder.getKey("initialised"))); - require(_STFactory != address(0) && _polyToken != address(0) && _owner != address(0) && _polymathRegistry != address(0), "In-valid address"); + require(_STFactory != address(0) && _polyToken != address(0) && _owner != address(0) && _polymathRegistry != address(0), "Invalid address"); require(_stLaunchFee != 0 && _tickerRegFee != 0, "Fees should not be 0"); - // address polyToken = _polyToken; set(Encoder.getKey("polyToken"), _polyToken); set(Encoder.getKey("stLaunchFee"), _stLaunchFee); set(Encoder.getKey("tickerRegFee"), _tickerRegFee); @@ -172,7 +165,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("paused"), false); set(Encoder.getKey("owner"), _owner); set(Encoder.getKey("polymathRegistry"), _polymathRegistry); - _setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(2)); + setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(2)); set(Encoder.getKey("initialised"), true); } @@ -192,18 +185,28 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_owner != address(0), "Owner should not be 0x"); require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); // Attempt to charge the reg fee if it is > 0 POLY - if (getUint(Encoder.getKey("tickerRegFee")) > 0) - require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), getUint(Encoder.getKey("tickerRegFee"))), "Sufficent allowance is not provided"); + uint256 tickerFee = getUint(Encoder.getKey("tickerRegFee")); + if (tickerFee > 0) + require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), tickerFee), "Insufficent allowance"); string memory ticker = Util.upper(_ticker); - require(_tickerAvailable(ticker), "Ticker is already reserved"); + require(_tickerAvailable(ticker), "Ticker is reserved"); // Check whether ticker was previously registered (and expired) - address previousOwner = getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + address previousOwner = getAddress(Encoder.getKey("registeredTickers_owner", ticker)); if (previousOwner != address(0)) { - _deleteTickerOwnership(previousOwner, _ticker); + _deleteTickerOwnership(previousOwner, ticker); } _addTicker(_owner, ticker, _tokenName, now, now.add(getUint(Encoder.getKey("expiryLimit"))), false, false); } + /** + * @notice Internal - Sets the details of the ticker + */ + function _addTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status, bool _fromAdmin) internal { + _setTickerOwnership(_owner, _ticker); + _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin); + } + /** * @notice Modifies the ticker details. Only Polymath has the ability to do so. * @notice Only allowed to modify the tickers which are not yet deployed. @@ -218,7 +221,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); require(_expiryDate != 0 && _registrationDate != 0, "Dates should not be 0"); require(_registrationDate <= _expiryDate, "Registration date should < expiry date"); - require(_owner != address(0), "In-valid address"); + require(_owner != address(0), "Invalid address"); string memory ticker = Util.upper(_ticker); _modifyTicker(_owner, ticker, _tokenName, _registrationDate, _expiryDate, _status); } @@ -228,19 +231,13 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function _modifyTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status) internal { address currentOwner = getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); - if (currentOwner == address(0) && _registrationDate == 0 && _expiryDate == 0) { - _addTicker(_owner, _ticker, _tokenName, now, now.add(getUint(Encoder.getKey("expiryLimit"))), _status, true); - return; - } - // If ticker exists, and is registered to a different owner, switch over - if ((currentOwner != address(0)) && (currentOwner != _owner)) { - _transferTickerOwnership(currentOwner, _owner, _ticker); + if (currentOwner != address(0)) { + _deleteTickerOwnership(currentOwner, _ticker); } - if (getBool(Encoder.getKey("registeredTickers_status", _ticker)) && !_status) { + if (_tickerStatus(_ticker) && !_status) { set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); } - _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, true); + _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true); } /** @@ -254,7 +251,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _deleteTickerOwnership(owner, ticker); set(Encoder.getKey("tickerToSecurityToken", ticker), address(0)); _storeTickerDetails(ticker, address(0), 0, 0, "", false); - emit TickerRemoved(_ticker, now, msg.sender); + emit TickerRemoved(ticker, now, msg.sender); } /** @@ -264,7 +261,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function _tickerAvailable(string _ticker) internal view returns(bool) { if (getAddress(Encoder.getKey("registeredTickers_owner", _ticker)) != address(0)) { - if (now > getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker)) && !getBool(Encoder.getKey("registeredTickers_status", _ticker))) { + if ((now > getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker))) && !_tickerStatus(_ticker)) { return true; } else return false; @@ -272,13 +269,8 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return true; } - /** - * @notice Internal - Sets the details of the ticker - */ - function _addTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status, bool _fromAdmin) internal { - _setTickerOwner(_owner, _ticker); - _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin); + function _tickerStatus(string _ticker) internal returns(bool) { + return getBool(Encoder.getKey("registeredTickers_status", _ticker)); } /** @@ -286,13 +278,14 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _owner is the address of the owner of the ticker * @param _ticker is the ticker symbol */ - function _setTickerOwner(address _owner, string _ticker) internal { + function _setTickerOwnership(address _owner, string _ticker) internal { uint256 length = uint256(getArrayBytes32(Encoder.getKey("userToTickers", _owner)).length); pushArray(Encoder.getKey("userToTickers", _owner), Util.stringToBytes32(_ticker)); set(Encoder.getKey("tickerIndex", _ticker), length); - if (!getBool(Encoder.getKey("seenUsers", _owner))) { + bytes32 seenKey = Encoder.getKey("seenUsers", _owner); + if (!getBool(seenKey)) { pushArray(Encoder.getKey("activeUsers"), _owner); - set(Encoder.getKey("seenUsers", _owner), true); + set(seenKey, true); } } @@ -300,16 +293,21 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Internal - Stores the ticker details */ function _storeTickerDetails(string _ticker, address _owner, uint256 _registrationDate, uint256 _expiryDate, string _tokenName, bool _status) internal { - if (getAddress(Encoder.getKey("registeredTickers_owner", _ticker)) != _owner) - set(Encoder.getKey("registeredTickers_owner", _ticker), _owner); - if (getUint(Encoder.getKey("registeredTickers_registrationDate", _ticker)) != _registrationDate) - set(Encoder.getKey("registeredTickers_registrationDate", _ticker), _registrationDate); - if (getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker)) != _expiryDate) - set(Encoder.getKey("registeredTickers_expiryDate", _ticker), _expiryDate); - if (Encoder.getKey(getString(Encoder.getKey("registeredTickers_tokenName", _ticker))) != Encoder.getKey(_tokenName)) - set(Encoder.getKey("registeredTickers_tokenName", _ticker), _tokenName); - if (getBool(Encoder.getKey("registeredTickers_status", _ticker)) != _status) - set(Encoder.getKey("registeredTickers_status", _ticker), _status); + bytes32 key = Encoder.getKey("registeredTickers_owner", _ticker); + if (getAddress(key) != _owner) + set(key, _owner); + key = Encoder.getKey("registeredTickers_registrationDate", _ticker); + if (getUint(key) != _registrationDate) + set(key, _registrationDate); + key = Encoder.getKey("registeredTickers_expiryDate", _ticker); + if (getUint(key) != _expiryDate) + set(key, _expiryDate); + key = Encoder.getKey("registeredTickers_tokenName", _ticker); + if (Encoder.getKey(getString(key)) != Encoder.getKey(_tokenName)) + set(key, _tokenName); + key = Encoder.getKey("registeredTickers_status", _ticker); + if (getBool(key) != _status) + set(key, _status); } /** @@ -319,39 +317,29 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function transferTickerOwnership(address _newOwner, string _ticker) external whenNotPausedOrOwner { string memory ticker = Util.upper(_ticker); - require(_newOwner != address(0), "In-valid address"); - require(getAddress(Encoder.getKey("registeredTickers_owner", ticker)) == msg.sender, "Not authorised"); - _transferTickerOwnership(msg.sender, _newOwner, ticker); - set(Encoder.getKey("registeredTickers_owner", ticker), _newOwner); - } - - /** - * @notice Internal - Transfers the control of ticker to a newOwner - * @param _oldOwner is the previous owner - * @param _newOwner is the the new owner - * @param _ticker is the ticker symbol - */ - function _transferTickerOwnership(address _oldOwner, address _newOwner, string _ticker) internal { - if(getBool(Encoder.getKey("registeredTickers_status", _ticker))) - require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", _ticker))).owner() == _newOwner, "Ticker can only be transferred to its token owner"); - - _deleteTickerOwnership(_oldOwner, _ticker); - _setTickerOwner(_newOwner, _ticker); - emit ChangeTickerOwnership(_ticker, _oldOwner, _newOwner); + require(_newOwner != address(0), "Invalid address"); + bytes32 ownerKey = Encoder.getKey("registeredTickers_owner", ticker); + require(getAddress(ownerKey) == msg.sender, "Not authorised"); + if (_tickerStatus(ticker)) + require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); + set(ownerKey, _newOwner); + _deleteTickerOwnership(msg.sender, ticker); + _setTickerOwnership(_newOwner, ticker); + emit ChangeTickerOwnership(ticker, msg.sender, _newOwner); } /** * @notice Internal - Removes the owner of a ticker */ function _deleteTickerOwnership(address _owner, string _ticker) internal { - uint256 _index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); - assert(_index < getArrayBytes32(Encoder.getKey("userToTickers", _owner)).length); - // deleting the _index from the data strucutre userToTickers[_oldowner][_index]; - deleteArrayBytes32(Encoder.getKey("userToTickers", _owner), _index); - - if (getArrayBytes32(Encoder.getKey("userToTickers", _owner)).length > _index) { - bytes32 switchedTicker = getArrayBytes32(Encoder.getKey("userToTickers", _owner))[_index]; - set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), _index); + uint256 index = uint256(getUint(Encoder.getKey("tickerIndex", _ticker))); + bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); + bytes32[] memory tickers = getArrayBytes32(ownerKey); + assert(index < tickers.length); + deleteArrayBytes32(Encoder.getKey("userToTickers", _owner), index); + if (tickers.length > index) { + bytes32 switchedTicker = tickers[index]; + set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); } } @@ -361,8 +349,9 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function changeExpiryLimit(uint256 _newExpiry) external onlyOwner { require(_newExpiry >= 1 days, "Expiry should >= 1 day"); - emit ChangeExpiryLimit(getUint(Encoder.getKey('expiryLimit')), _newExpiry); - set(Encoder.getKey('expiryLimit'), _newExpiry); + bytes32 key = Encoder.getKey('expiryLimit'); + emit ChangeExpiryLimit(getUint(key), _newExpiry); + set(key, _newExpiry); } /** @@ -372,12 +361,12 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { function getTickersByOwner(address _owner) external view returns(bytes32[]) { uint counter = 0; // accessing the data structure userTotickers[_owner].length - uint _len = getArrayBytes32(Encoder.getKey("userToTickers", _owner)).length; - bytes32[] memory tempList = new bytes32[](_len); - for (uint i = 0; i < _len; i++) { - string memory _ticker = Util.bytes32ToString(getArrayBytes32(Encoder.getKey("userToTickers", _owner))[i]); - if (getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker)) >= now || getBool(Encoder.getKey("registeredTickers_status", _ticker))) { - tempList[counter] = getArrayBytes32(Encoder.getKey("userToTickers", _owner))[i]; + bytes32[] memory tickers = getArrayBytes32(Encoder.getKey("userToTickers", _owner)); + bytes32[] memory tempList = new bytes32[](tickers.length); + for (uint i = 0; i < tickers.length; i++) { + string memory ticker = Util.bytes32ToString(tickers[i]); + if (getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now || _tickerStatus(ticker)) { + tempList[counter] = tickers[i]; counter ++; } } @@ -437,14 +426,16 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function getTickerDetails(string _ticker) external view returns (address, uint256, uint256, string, bool) { string memory ticker = Util.upper(_ticker); - if (getBool(Encoder.getKey("registeredTickers_status", ticker)) == true || getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) > now) { + bool tickerStatus = _tickerStatus(ticker); + uint256 expiryDate = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); + if ((tickerStatus == true) || (expiryDate > now)) { return ( getAddress(Encoder.getKey("registeredTickers_owner", ticker)), getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), - getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)), + expiryDate, getString(Encoder.getKey("registeredTickers_tokenName", ticker)), - getBool(Encoder.getKey("registeredTickers_status", ticker)) + tickerStatus ); } else return (address(0), uint256(0), uint256(0), "", false); @@ -464,15 +455,15 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { function generateSecurityToken(string _name, string _ticker, string _tokenDetails, bool _divisible) external whenNotPausedOrOwner { require(bytes(_name).length > 0 && bytes(_ticker).length > 0, "Ticker length > 0"); string memory ticker = Util.upper(_ticker); - - require(getBool(Encoder.getKey("registeredTickers_status", ticker)) != true, "Already deployed"); + bytes32 statusKey = Encoder.getKey("registeredTickers_status", ticker); + require(getBool(statusKey) != true, "Already deployed"); + set(statusKey, true); require(getAddress(Encoder.getKey("registeredTickers_owner", ticker)) == msg.sender, "Not authorised"); require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); - set(Encoder.getKey("registeredTickers_status", ticker), true); - - if (getUint(Encoder.getKey("stLaunchFee")) > 0) - require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), getUint(Encoder.getKey("stLaunchFee"))), "Insufficient allowance"); + uint256 launchFee = getUint(Encoder.getKey("stLaunchFee")); + if (launchFee > 0) + require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); address newSecurityTokenAddress = ISTFactory(getSTFactoryAddress()).deployToken( _name, @@ -566,8 +557,9 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { */ function transferOwnership(address _newOwner) external onlyOwner { require(_newOwner != address(0)); - emit OwnershipTransferred(getAddress(Encoder.getKey("owner")), _newOwner); - set(Encoder.getKey("owner"), _newOwner); + bytes32 key = Encoder.getKey("owner"); + emit OwnershipTransferred(getAddress(key), _newOwner); + set(key, _newOwner); } /** @@ -591,9 +583,11 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _tickerRegFee is the registration fee in POLY tokens (base 18 decimals) */ function changeTickerRegistrationFee(uint256 _tickerRegFee) external onlyOwner { - require(getUint(Encoder.getKey('tickerRegFee')) != _tickerRegFee); - emit ChangeTickerRegistrationFee(getUint(Encoder.getKey('tickerRegFee')), _tickerRegFee); - set(Encoder.getKey('tickerRegFee'), _tickerRegFee); + bytes32 key = Encoder.getKey('tickerRegFee'); + uint256 fee = getUint(key); + require(fee != _tickerRegFee); + emit ChangeTickerRegistrationFee(fee, _tickerRegFee); + set(key, _tickerRegFee); } /** @@ -601,9 +595,11 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _stLaunchFee is the registration fee in POLY tokens (base 18 decimals) */ function changeSecurityLaunchFee(uint256 _stLaunchFee) external onlyOwner { - require(getUint(Encoder.getKey("stLaunchFee")) != _stLaunchFee); - emit ChangeSecurityLaunchFee(getUint(Encoder.getKey("stLaunchFee")), _stLaunchFee); - set(Encoder.getKey("stLaunchFee"), _stLaunchFee); + bytes32 key = Encoder.getKey('stLaunchFee'); + uint256 fee = getUint(key); + require(fee != _stLaunchFee); + emit ChangeSecurityLaunchFee(fee, _stLaunchFee); + set(key, _stLaunchFee); } /** @@ -626,22 +622,15 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _minor Minor version of the proxy. * @param _patch Patch version of the proxy */ - function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { - _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); - } - - /** - * @notice Internal - Changes the protocol version and the SecurityToken contract - */ - function _setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) internal { + function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) public onlyOwner { uint8[] memory _version = new uint8[](3); _version[0] = _major; _version[1] = _minor; _version[2] = _patch; uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); - require(VersionUtils.isValidVersion(getProtocolVersion(), _version),"In-valid version"); + require(VersionUtils.isValidVersion(getProtocolVersion(), _version),"Invalid version"); set(Encoder.getKey("latestVersion"), uint256(_packedVersion)); - set(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))), _STFactoryAddress); + set(Encoder.getKey("protocolVersionST", uint256(_packedVersion)), _STFactoryAddress); } /** diff --git a/contracts/interfaces/IOwnable.sol b/contracts/interfaces/IOwnable.sol index 15849e181..de8a8d14f 100644 --- a/contracts/interfaces/IOwnable.sol +++ b/contracts/interfaces/IOwnable.sol @@ -10,7 +10,7 @@ interface IOwnable { /** * @dev Returns owner */ - function owner() external returns (address); + function owner() external view returns (address); /** * @dev Allows the current owner to relinquish control of the contract. diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 444fb5375..d7ec8f9f0 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -84,7 +84,7 @@ interface ISecurityTokenRegistry { /** * @notice get Protocol version */ - function getProtocolVersion() public view returns(uint8[]); + function getProtocolVersion() external view returns(uint8[]); /** * @notice Use to get the ticker list as per the owner diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 137ffc30b..6c866a7df 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -99,6 +99,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr // Records added module names - module list should be order agnostic! mapping (bytes32 => address[]) names; + // List of investors mapping (address => bool) public investorListed; // Emit at the time when module get added @@ -141,7 +142,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr event ForceTransfer(address indexed _controller, address indexed _from, address indexed _to, uint256 _amount, bool _verifyTransfer, bytes _data); event DisableController(uint256 _timestamp); - function isModule(address _module, uint8 _type) internal view returns (bool) { + function _isModule(address _module, uint8 _type) internal view returns (bool) { require(modulesToData[_module].module == _module, "Address mismatch"); require(modulesToData[_module].moduleType == _type, "Type mismatch"); require(!modulesToData[_module].isArchived, "Module archived"); @@ -150,7 +151,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr // Require msg.sender to be the specified module type modifier onlyModule(uint8 _type) { - require(isModule(msg.sender, _type)); + require(_isModule(msg.sender, _type)); _; } @@ -159,7 +160,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr if (msg.sender == owner) { _; } else { - require(isModule(msg.sender, _type)); + require(_isModule(msg.sender, _type)); _; } } From e94e0255f0194ebc9f1c0ba10bbae530b3f8dd2a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 30 Sep 2018 18:58:09 +0100 Subject: [PATCH 02/19] WIP --- contracts/SecurityTokenRegistry.sol | 21 ++++++++++----------- test/n_security_token_registry.js | 7 +++---- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 9ec100df1..882a58ba4 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -78,8 +78,6 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // Emit when ownership of the ticker gets changed event ChangeTickerOwnership(string _ticker, address indexed _oldOwner, address indexed _newOwner); - // Emit when a ticker details is modified - event ModifyTickerDetails(address _owner, string _ticker, string _name, uint256 _registrationDate, uint256 _expiryDate, bool _status); // Emit at the time of launching a new security token event NewSecurityToken( string _ticker, @@ -622,15 +620,16 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _minor Minor version of the proxy. * @param _patch Patch version of the proxy */ - function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) public onlyOwner { - uint8[] memory _version = new uint8[](3); - _version[0] = _major; - _version[1] = _minor; - _version[2] = _patch; - uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); - require(VersionUtils.isValidVersion(getProtocolVersion(), _version),"Invalid version"); - set(Encoder.getKey("latestVersion"), uint256(_packedVersion)); - set(Encoder.getKey("protocolVersionST", uint256(_packedVersion)), _STFactoryAddress); + function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) public { + uint8[] memory version = new uint8[](3); + version[0] = _major; + version[1] = _minor; + version[2] = _patch; + uint24 packedVersion = VersionUtils.pack(_major, _minor, _patch); + require(VersionUtils.isValidVersion(getProtocolVersion(), version),"Invalid version"); + set(Encoder.getKey("latestVersion"), uint256(packedVersion)); + set(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))), _STFactoryAddress); + /* set(Encoder.getKey("protocolVersionST", uint256(_packedVersion)), _STFactoryAddress); */ } /** diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index a53378c8b..d9e3cdf98 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -131,7 +131,7 @@ contract('SecurityTokenRegistry', accounts => { }); // STEP 3: Deploy the ModuleRegistry - + 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}); @@ -203,7 +203,7 @@ contract('SecurityTokenRegistry', accounts => { "SecurityTokenRegistry contract was not deployed", ); - // Step 9 (a): Deploy the proxy + // Step 9 (a): Deploy the proxy 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}); @@ -833,8 +833,7 @@ contract('SecurityTokenRegistry', accounts => { it("Should change the details of the existing ticker", async() => { let tx = await I_STRProxied.modifyTicker(token_owner, "ETH", "Ether", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); - assert.equal(tx.logs[0].args._oldOwner, account_temp); - assert.equal(tx.logs[0].args._newOwner, token_owner); + assert.equal(tx.logs[0].args._owner, token_owner); }); }); From cd952c3a9119556101755ce4bb105f62436c3c50 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 30 Sep 2018 19:43:10 +0100 Subject: [PATCH 03/19] Updates --- contracts/SecurityTokenRegistry.sol | 37 ++++++++++++++++++++++------- test/n_security_token_registry.js | 9 ++++++- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 882a58ba4..c8174e258 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -183,13 +183,13 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_owner != address(0), "Owner should not be 0x"); require(bytes(_ticker).length > 0 && bytes(_ticker).length <= 10, "Ticker length range (0,10]"); // Attempt to charge the reg fee if it is > 0 POLY - uint256 tickerFee = getUint(Encoder.getKey("tickerRegFee")); + uint256 tickerFee = getTickerRegistrationFee(); if (tickerFee > 0) require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), tickerFee), "Insufficent allowance"); string memory ticker = Util.upper(_ticker); require(_tickerAvailable(ticker), "Ticker is reserved"); // Check whether ticker was previously registered (and expired) - address previousOwner = getAddress(Encoder.getKey("registeredTickers_owner", ticker)); + address previousOwner = _tickerOwner(ticker); if (previousOwner != address(0)) { _deleteTickerOwnership(previousOwner, ticker); } @@ -228,7 +228,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Internal -- Modifies the ticker details. */ function _modifyTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status) internal { - address currentOwner = getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + address currentOwner = _tickerOwner(_ticker); if (currentOwner != address(0)) { _deleteTickerOwnership(currentOwner, _ticker); } @@ -238,13 +238,17 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true); } + function _tickerOwner(string _ticker) internal view returns(address) { + return getAddress(Encoder.getKey("registeredTickers_owner", _ticker)); + } + /** * @notice Removes the ticker details, associated ownership & security token mapping * @param _ticker is the token ticker */ function removeTicker(string _ticker) external onlyOwner { string memory ticker = Util.upper(_ticker); - address owner = getAddress(Encoder.getKey("registeredTickers_owner", ticker)); + address owner = _tickerOwner(ticker); require(owner != address(0), "Ticker doesn't exist"); _deleteTickerOwnership(owner, ticker); set(Encoder.getKey("tickerToSecurityToken", ticker), address(0)); @@ -258,7 +262,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @return bool */ function _tickerAvailable(string _ticker) internal view returns(bool) { - if (getAddress(Encoder.getKey("registeredTickers_owner", _ticker)) != address(0)) { + if (_tickerOwner(_ticker) != address(0)) { if ((now > getUint(Encoder.getKey("registeredTickers_expiryDate", _ticker))) && !_tickerStatus(_ticker)) { return true; } else @@ -320,9 +324,9 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(getAddress(ownerKey) == msg.sender, "Not authorised"); if (_tickerStatus(ticker)) require(IOwnable(getAddress(Encoder.getKey("tickerToSecurityToken", ticker))).owner() == _newOwner, "New owner does not match token owner"); - set(ownerKey, _newOwner); _deleteTickerOwnership(msg.sender, ticker); _setTickerOwnership(_newOwner, ticker); + set(ownerKey, _newOwner); emit ChangeTickerOwnership(ticker, msg.sender, _newOwner); } @@ -429,7 +433,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if ((tickerStatus == true) || (expiryDate > now)) { return ( - getAddress(Encoder.getKey("registeredTickers_owner", ticker)), + _tickerOwner(ticker), getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), expiryDate, getString(Encoder.getKey("registeredTickers_tokenName", ticker)), @@ -456,10 +460,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bytes32 statusKey = Encoder.getKey("registeredTickers_status", ticker); require(getBool(statusKey) != true, "Already deployed"); set(statusKey, true); - require(getAddress(Encoder.getKey("registeredTickers_owner", ticker)) == msg.sender, "Not authorised"); + require(_tickerOwner(ticker) == msg.sender, "Not authorised"); require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); - uint256 launchFee = getUint(Encoder.getKey("stLaunchFee")); + uint256 launchFee = getSecurityTokenLaunchFee(); if (launchFee > 0) require(IERC20(getAddress(Encoder.getKey("polyToken"))).transferFrom(msg.sender, address(this), launchFee), "Insufficient allowance"); @@ -655,5 +659,20 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("polyToken"), _newAddress); } + /** + * @notice Gets the security token launch fee + * @return Fee amount + */ + function getSecurityTokenLaunchFee() public view returns(uint256) { + return getUint(Encoder.getKey("stLaunchFee")); + } + + /** + * @notice Gets the ticker registration fee + * @return Fee amount + */ + function getTickerRegistrationFee() public view returns(uint256) { + return getUint(Encoder.getKey("tickerRegFee")); + } } diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index d9e3cdf98..a729f2d37 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -739,9 +739,15 @@ contract('SecurityTokenRegistry', accounts => { // Register the new ticker -- Fulfiling the TickerStatus.ON condition await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: account_temp}); + let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); await I_STRProxied.registerTicker(account_temp, "LOG", "LOGAN", { from : account_temp }); + tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); // Generating the ST let tx = await I_STRProxied.modifySecurityToken("LOGAN", "LOG", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); + console.log(tickersListArray); assert.equal(tx.logs[1].args._ticker, "LOG", "Symbol should match with the registered symbol"); assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token,`Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); let symbolDetails = await I_STRProxied.getTickerDetails("LOG"); @@ -1082,7 +1088,8 @@ contract('SecurityTokenRegistry', accounts => { let tickersList = await I_STRProxied.getTickersByOwner.call(token_owner); assert.equal(tickersList.length, 4); let tickersListArray = await I_STRProxied.getTickersByOwner.call(account_temp); - assert.equal(tickersListArray.length, 2); + console.log(tickersListArray); + assert.equal(tickersListArray.length, 3); }); }); From e425691a342856994561d4bf4c97a7585cad004b Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 30 Sep 2018 20:23:06 +0100 Subject: [PATCH 04/19] Add assertion --- contracts/SecurityTokenRegistry.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index c8174e258..d6fb7b562 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -338,6 +338,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bytes32 ownerKey = Encoder.getKey("userToTickers", _owner); bytes32[] memory tickers = getArrayBytes32(ownerKey); assert(index < tickers.length); + assert(_tickerOwner(_ticker) == _owner); deleteArrayBytes32(Encoder.getKey("userToTickers", _owner), index); if (tickers.length > index) { bytes32 switchedTicker = tickers[index]; From 7ad0c19375cccdff960729205d45873c12610e0a Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Sun, 30 Sep 2018 20:26:29 +0100 Subject: [PATCH 05/19] Update interface --- contracts/SecurityTokenRegistry.sol | 10 +++++++++- .../interfaces/ISecurityTokenRegistry.sol | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index d6fb7b562..671cd5c82 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -193,7 +193,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (previousOwner != address(0)) { _deleteTickerOwnership(previousOwner, ticker); } - _addTicker(_owner, ticker, _tokenName, now, now.add(getUint(Encoder.getKey("expiryLimit"))), false, false); + _addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false); } /** @@ -676,4 +676,12 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return getUint(Encoder.getKey("tickerRegFee")); } + /** + * @notice Gets the expiry limit + * @return Expiry limit + */ + function getExpiryLimit() public view returns(uint256) { + return getUint(Encoder.getKey("expiryLimit")); + } + } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index d7ec8f9f0..87c02cc90 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -159,4 +159,22 @@ interface ISecurityTokenRegistry { */ function updatePolyTokenAddress(address _newAddress) external; + /** + * @notice Gets the security token launch fee + * @return Fee amount + */ + function getSecurityTokenLaunchFee() external view returns(uint256); + + /** + * @notice Gets the ticker registration fee + * @return Fee amount + */ + function getTickerRegistrationFee() external view returns(uint256); + + /** + * @notice Gets the expiry limit + * @return Expiry limit + */ + function getExpiryLimit() external view returns(uint256); + } From c92ed874324c721423f47ab081a3ff7cdbc3dbdf Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 1 Oct 2018 12:53:08 +0530 Subject: [PATCH 06/19] minor fixes to reduce the size --- contracts/SecurityTokenRegistry.sol | 24 +++++++++++++------ .../interfaces/ISecurityTokenRegistry.sol | 6 +++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 671cd5c82..b8e73dbe1 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -117,7 +117,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (msg.sender == getAddress(Encoder.getKey("owner"))) _; else { - require(!getBool(Encoder.getKey("paused")), "Already paused"); + require(!isPaused(), "Already paused"); _; } } @@ -126,7 +126,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Modifier to make a function callable only when the contract is not paused and ignore is msg.sender is owner. */ modifier whenNotPaused() { - require(!getBool(Encoder.getKey("paused")), "Already paused"); + require(!isPaused(), "Already paused"); _; } @@ -135,10 +135,11 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { - require(getBool(Encoder.getKey("paused")), "Should not be paused"); + require(isPaused(), "Should not be paused"); _; } + ///////////////////////////// // Initialization ///////////////////////////// @@ -281,8 +282,9 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _ticker is the ticker symbol */ function _setTickerOwnership(address _owner, string _ticker) internal { - uint256 length = uint256(getArrayBytes32(Encoder.getKey("userToTickers", _owner)).length); - pushArray(Encoder.getKey("userToTickers", _owner), Util.stringToBytes32(_ticker)); + bytes32 _ownerKey = Encoder.getKey("userToTickers", _owner); + uint256 length = uint256(getArrayBytes32(_ownerKey).length); + pushArray(_ownerKey, Util.stringToBytes32(_ticker)); set(Encoder.getKey("tickerIndex", _ticker), length); bytes32 seenKey = Encoder.getKey("seenUsers", _owner); if (!getBool(seenKey)) { @@ -339,7 +341,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { bytes32[] memory tickers = getArrayBytes32(ownerKey); assert(index < tickers.length); assert(_tickerOwner(_ticker) == _owner); - deleteArrayBytes32(Encoder.getKey("userToTickers", _owner), index); + deleteArrayBytes32(ownerKey, index); if (tickers.length > index) { bytes32 switchedTicker = tickers[index]; set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); @@ -459,7 +461,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(bytes(_name).length > 0 && bytes(_ticker).length > 0, "Ticker length > 0"); string memory ticker = Util.upper(_ticker); bytes32 statusKey = Encoder.getKey("registeredTickers_status", ticker); - require(getBool(statusKey) != true, "Already deployed"); + require(!getBool(statusKey), "Already deployed"); set(statusKey, true); require(_tickerOwner(ticker) == msg.sender, "Not authorised"); require(getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)) >= now, "Ticker gets expired"); @@ -684,4 +686,12 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return getUint(Encoder.getKey("expiryLimit")); } + /** + * @notice Check whether the registry is paused or not + * @return bool + */ + function isPaused() public view returns(bool) { + return getBool(Encoder.getKey("paused")); + } + } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 87c02cc90..5231e8ef4 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -177,4 +177,10 @@ interface ISecurityTokenRegistry { */ function getExpiryLimit() external view returns(uint256); + /** + * @notice Check whether the registry is paused or not + * @return bool + */ + function isPaused() public view returns(bool); + } From 0ea44ab58ac59603134ab1d051048b97e091a5aa Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 10:31:42 +0100 Subject: [PATCH 07/19] Revert changes to setProtocol --- contracts/SecurityTokenRegistry.sol | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index b8e73dbe1..9e568c94c 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -164,7 +164,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("paused"), false); set(Encoder.getKey("owner"), _owner); set(Encoder.getKey("polymathRegistry"), _polymathRegistry); - setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(2)); + _setProtocolVersion(_STFactory, uint8(0), uint8(0), uint8(2)); set(Encoder.getKey("initialised"), true); } @@ -627,16 +627,22 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @param _minor Minor version of the proxy. * @param _patch Patch version of the proxy */ - function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) public { - uint8[] memory version = new uint8[](3); - version[0] = _major; - version[1] = _minor; - version[2] = _patch; - uint24 packedVersion = VersionUtils.pack(_major, _minor, _patch); - require(VersionUtils.isValidVersion(getProtocolVersion(), version),"Invalid version"); - set(Encoder.getKey("latestVersion"), uint256(packedVersion)); + function setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) external onlyOwner { + _setProtocolVersion(_STFactoryAddress, _major, _minor, _patch); + } + + /** + * @notice Internal - Changes the protocol version and the SecurityToken contract + */ + function _setProtocolVersion(address _STFactoryAddress, uint8 _major, uint8 _minor, uint8 _patch) internal { + uint8[] memory _version = new uint8[](3); + _version[0] = _major; + _version[1] = _minor; + _version[2] = _patch; + uint24 _packedVersion = VersionUtils.pack(_major, _minor, _patch); + require(VersionUtils.isValidVersion(getProtocolVersion(), _version),"In-valid version"); + set(Encoder.getKey("latestVersion"), uint256(_packedVersion)); set(Encoder.getKey("protocolVersionST", getUint(Encoder.getKey("latestVersion"))), _STFactoryAddress); - /* set(Encoder.getKey("protocolVersionST", uint256(_packedVersion)), _STFactoryAddress); */ } /** From 04fb3a18f3b00299d4b1bef0e46edc7a23642836 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 12:00:53 +0100 Subject: [PATCH 08/19] Only allow STs to be added if there is a valid ticker registration first --- contracts/SecurityTokenRegistry.sol | 9 +++++++-- test/n_security_token_registry.js | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 9e568c94c..8b7a3bd77 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -236,6 +236,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (_tickerStatus(_ticker) && !_status) { set(Encoder.getKey("tickerToSecurityToken", _ticker), address(0)); } + // If status is true, there must be a security token linked to the ticker already + if (_status) { + require(getAddress(Encoder.getKey("tickerToSecurityToken", _ticker)) != address(0), "Token not registered"); + } _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true); } @@ -500,9 +504,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_deployedAt != 0 && _owner != address(0), "0 value params not allowed"); string memory ticker = Util.upper(_ticker); require(_securityToken != address(0), "ST address is 0x"); - // If ticker didn't previously exist, it will be created - _modifyTicker(_owner, ticker, _name, getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)), true); + // If ticker doesn't exist, then we will fail - must call modifyTicker first + require(_tickerOwner(ticker) != address(0), "Ticker not registered"); set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); + _modifyTicker(_owner, ticker, _name, getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)), true); _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true); } diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index a729f2d37..1a47b82bf 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -757,6 +757,17 @@ contract('SecurityTokenRegistry', accounts => { it("Should successfully generate the custom token", async() => { // Fulfilling the TickerStatus.NN condition + let errorThrown = false; + try { + await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + } catch(error) { + console.log(` tx revert -> because ticker not registered`.grey); + errorThrown = true; + ensureException(error); + } + assert.ok(errorThrown, message); + await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); + await increaseTime(duration.days(1)); let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); From 6621d9e66cf5f1da52cb4c214d57924a97b1e4e9 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 12:15:42 +0100 Subject: [PATCH 09/19] Change logic to allow tickers to be registered directly when modifying security tokens --- contracts/SecurityTokenRegistry.sol | 10 +++++++--- test/n_security_token_registry.js | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 8b7a3bd77..d3c12ac19 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -504,10 +504,14 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_deployedAt != 0 && _owner != address(0), "0 value params not allowed"); string memory ticker = Util.upper(_ticker); require(_securityToken != address(0), "ST address is 0x"); - // If ticker doesn't exist, then we will fail - must call modifyTicker first - require(_tickerOwner(ticker) != address(0), "Ticker not registered"); + uint256 registrationTime = getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)); + uint256 expiryTime = getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)); + if (registrationTime == 0) { + registrationTime = now; + expiryTime = registrationTime.add(getExpiryLimit()); + } set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); - _modifyTicker(_owner, ticker, _name, getUint(Encoder.getKey("registeredTickers_registrationDate", ticker)), getUint(Encoder.getKey("registeredTickers_expiryDate", ticker)), true); + _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true); } diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 1a47b82bf..5b09d6160 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -757,17 +757,17 @@ contract('SecurityTokenRegistry', accounts => { it("Should successfully generate the custom token", async() => { // Fulfilling the TickerStatus.NN condition - let errorThrown = false; - try { - await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); - } catch(error) { - console.log(` tx revert -> because ticker not registered`.grey); - errorThrown = true; - ensureException(error); - } - assert.ok(errorThrown, message); - await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); - await increaseTime(duration.days(1)); + // let errorThrown = false; + // try { + // await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); + // } catch(error) { + // console.log(` tx revert -> because ticker not registered`.grey); + // errorThrown = true; + // ensureException(error); + // } + // assert.ok(errorThrown, message); + // await I_STRProxied.modifyTicker(account_temp, "LOG2", "LOGAN2", latestTime(), latestTime() + duration.days(10), false, {from: account_polymath}); + // await increaseTime(duration.days(1)); let tx = await I_STRProxied.modifySecurityToken("LOGAN2", "LOG2", account_temp, dummy_token, "I am custom ST", latestTime(), {from: account_polymath}); assert.equal(tx.logs[1].args._ticker, "LOG2", "Symbol should match with the registered symbol"); assert.equal(tx.logs[1].args._securityTokenAddress, dummy_token, `Address of the SecurityToken should be matched with the input value of addCustomSecurityToken`); From 6deb8e2c29490e3cde62c3087675d02d66d07f2e Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Mon, 1 Oct 2018 10:09:28 -0300 Subject: [PATCH 10/19] CLI: STR getters for fees and expiry limit --- CLI/commands/ST20Generator.js | 6 ++---- CLI/commands/TickerRollForward.js | 4 +--- CLI/commands/contract_manager.js | 9 +++------ 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/CLI/commands/ST20Generator.js b/CLI/commands/ST20Generator.js index 27ae398b2..73a674434 100644 --- a/CLI/commands/ST20Generator.js +++ b/CLI/commands/ST20Generator.js @@ -19,8 +19,6 @@ let tokenSymbol; let selectedSTO; const STO_KEY = 3; -const REG_FEE_KEY = 'tickerRegFee'; -const LAUNCH_FEE_KEY = 'stLaunchFee'; const cappedSTOFee = 20000; const usdTieredSTOFee = 100000; const tokenDetails = ""; @@ -111,7 +109,7 @@ async function step_ticker_reg(){ console.log('\n\x1b[34m%s\x1b[0m',"Token Creation - Symbol Registration"); let available = false; - let regFee = web3.utils.fromWei(await securityTokenRegistry.methods.getUintValues(web3.utils.soliditySha3(REG_FEE_KEY)).call()); + let regFee = web3.utils.fromWei(await securityTokenRegistry.methods.getTickerRegistrationFee().call()); while (!available) { console.log(chalk.green(`\nRegistering the new token symbol requires ${regFee} POLY & deducted from '${Issuer.address}', Current balance is ${(await currentBalance(Issuer.address))} POLY\n`)); @@ -160,7 +158,7 @@ async function step_token_deploy(){ } else { console.log('\n\x1b[34m%s\x1b[0m',"Token Creation - Token Deployment"); - let launchFee = web3.utils.fromWei(await securityTokenRegistry.methods.getUintValues(web3.utils.soliditySha3(LAUNCH_FEE_KEY)).call()); + let launchFee = web3.utils.fromWei(await securityTokenRegistry.methods.getSecurityTokenLaunchFee().call()); console.log(chalk.green(`\nToken deployment requires ${launchFee} POLY & deducted from '${Issuer.address}', Current balance is ${(await currentBalance(Issuer.address))} POLY\n`)); if (typeof _tokenConfig !== 'undefined' && _tokenConfig.hasOwnProperty('name')) { diff --git a/CLI/commands/TickerRollForward.js b/CLI/commands/TickerRollForward.js index 732eb1b97..97bd1f519 100644 --- a/CLI/commands/TickerRollForward.js +++ b/CLI/commands/TickerRollForward.js @@ -13,8 +13,6 @@ var abis = require('./helpers/contract_abis'); let remoteNetwork = process.argv.slice(2)[0]; //batch size ///////////////////////// GLOBAL VARS ///////////////////////// -const REG_FEE_KEY = 'tickerRegFee'; - let ticker_data = []; let registered_tickers = []; let failed_tickers = []; @@ -80,7 +78,7 @@ async function readFile() { async function registerTickers() { // Poly approval for registration fees let polyBalance = BigNumber(await polyToken.methods.balanceOf(Issuer.address).call()); - let fee = web3.utils.fromWei(await securityTokenRegistry.methods.getUintValues(web3.utils.soliditySha3(REG_FEE_KEY)).call()); + let fee = web3.utils.fromWei(await securityTokenRegistry.methods.getTickerRegistrationFee().call()); let totalFee = BigNumber(ticker_data.length).mul(fee); if (totalFee.gt(polyBalance)) { diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index 60af89396..0406dc191 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -14,9 +14,6 @@ var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); const OWNER_KEY = 'owner'; -const REG_FEE_KEY = 'tickerRegFee'; -const LAUNCH_FEE_KEY = 'stLaunchFee'; -const EXPIRY_LIMIT_KEY = 'expiryLimit'; // App flow let currentContract = null; @@ -168,7 +165,7 @@ async function strActions() { console.log(chalk.green(`Security Token has been updated successfuly`)); break; case 'Change Expiry Limit': - let currentExpiryLimit = await currentContract.methods.getUintValues(web3.utils.soliditySha3(EXPIRY_LIMIT_KEY)).call(); + let currentExpiryLimit = await currentContract.methods.getExpiryLimit().call(); console.log(chalk.yellow(`Current expiry limit is ${Math.floor(parseInt(currentExpiryLimit)/60/60/24)} days`)); let newExpiryLimit = duration.days(readlineSync.questionInt('Enter a new value in days for expiry limit: ')); let changeExpiryLimitAction = currentContract.methods.changeExpiryLimit(newExpiryLimit); @@ -177,7 +174,7 @@ async function strActions() { console.log(chalk.green(`Expiry limit was changed successfuly. New limit is ${Math.floor(parseInt(changeExpiryLimitEvent._newExpiry)/60/60/24)} days\n`)); break; case 'Change registration fee': - let currentRegFee = web3.utils.fromWei(await currentContract.methods.getUintValues(web3.utils.soliditySha3(REG_FEE_KEY)).call()); + let currentRegFee = web3.utils.fromWei(await currentContract.methods.getTickerRegistrationFee().call()); console.log(chalk.yellow(`\nCurrent ticker registration fee is ${currentRegFee} POLY`)); let newRegFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ticker registration fee: ').toString()); let changeRegFeeAction = currentContract.methods.changeTickerRegistrationFee(newRegFee); @@ -186,7 +183,7 @@ async function strActions() { console.log(chalk.green(`Fee was changed successfuly. New fee is ${web3.utils.fromWei(changeRegFeeEvent._newFee)} POLY\n`)); break; case 'Change ST launch fee': - let currentLaunchFee = web3.utils.fromWei(await currentContract.methods.getUintValues(web3.utils.soliditySha3(LAUNCH_FEE_KEY)).call()); + let currentLaunchFee = web3.utils.fromWei(await currentContract.methods.getSecurityTokenLaunchFee().call()); console.log(chalk.yellow(`\nCurrent ST launch fee is ${currentLaunchFee} POLY`)); let newLaunchFee = web3.utils.toWei(readlineSync.questionInt('Enter a new value in POLY for ST launch fee: ').toString()); let changeLaunchFeeAction = currentContract.methods.changeSecurityLaunchFee(newLaunchFee); From 7eddf7df3113557442f71fc9090cce785404aad7 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Mon, 1 Oct 2018 10:12:15 -0300 Subject: [PATCH 11/19] CLI typo --- CLI/commands/contract_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index 0406dc191..07d89d48e 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -114,7 +114,7 @@ async function strActions() { console.log(chalk.green(`Ticker has been updated successfuly`)); break; case 'Remove Ticker': - let tickerToRemove = readlineSync.question('Enter the token symbol that you want to add or modify: '); + let tickerToRemove = readlineSync.question('Enter the token symbol that you want to remove: '); let tickerToRemoveDetails = await currentContract.methods.getTickerDetails(tickerToRemove).call(); if (tickerToRemoveDetails[1] == 0) { console.log(chalk.yellow(`${ticker} does not exist.`)); From 27e13cb999d9e6d86222c13d549664085b38895d Mon Sep 17 00:00:00 2001 From: satyam Date: Mon, 1 Oct 2018 18:48:23 +0530 Subject: [PATCH 12/19] minor fixes --- contracts/SecurityTokenRegistry.sol | 32 ++++++++++++------- .../interfaces/ISecurityTokenRegistry.sol | 8 ++++- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index d3c12ac19..926183238 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -86,7 +86,8 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { address indexed _owner, uint256 _addedAt, address _registrant, - bool _fromAdmin + bool _fromAdmin, + uint256 _registrationFee ); // Emit after ticker registration event RegisterTicker( @@ -95,7 +96,8 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { string _name, uint256 indexed _registrationDate, uint256 indexed _expiryDate, - bool _fromAdmin + bool _fromAdmin, + uint256 _registrationFee ); ///////////////////////////// @@ -106,7 +108,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { - require(msg.sender == getAddress(Encoder.getKey("owner"))); + require(msg.sender == owner()); _; } @@ -114,7 +116,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { * @notice Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPausedOrOwner() { - if (msg.sender == getAddress(Encoder.getKey("owner"))) + if (msg.sender == owner()) _; else { require(!isPaused(), "Already paused"); @@ -194,16 +196,16 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (previousOwner != address(0)) { _deleteTickerOwnership(previousOwner, ticker); } - _addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false); + _addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, getTickerRegistrationFee()); } /** * @notice Internal - Sets the details of the ticker */ - function _addTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status, bool _fromAdmin) internal { + function _addTicker(address _owner, string _ticker, string _tokenName, uint256 _registrationDate, uint256 _expiryDate, bool _status, bool _fromAdmin, uint256 _fee) internal { _setTickerOwnership(_owner, _ticker); _storeTickerDetails(_ticker, _owner, _registrationDate, _expiryDate, _tokenName, _status); - emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin); + emit RegisterTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _fromAdmin, _fee); } /** @@ -240,7 +242,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (_status) { require(getAddress(Encoder.getKey("tickerToSecurityToken", _ticker)) != address(0), "Token not registered"); } - _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true); + _addTicker(_owner, _ticker, _tokenName, _registrationDate, _expiryDate, _status, true, uint256(0)); } function _tickerOwner(string _ticker) internal view returns(address) { @@ -486,7 +488,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _storeSecurityTokenData(newSecurityTokenAddress, ticker, _tokenDetails, now); set(Encoder.getKey("tickerToSecurityToken", ticker), newSecurityTokenAddress); - emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false); + emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false, getSecurityTokenLaunchFee()); } /** @@ -513,7 +515,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { set(Encoder.getKey("tickerToSecurityToken", ticker), _securityToken); _modifyTicker(_owner, ticker, _name, registrationTime, expiryTime, true); _storeSecurityTokenData(_securityToken, ticker, _tokenDetails, _deployedAt); - emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true); + emit NewSecurityToken(ticker, _name, _securityToken, _owner, _deployedAt, msg.sender, true, getSecurityTokenLaunchFee()); } /** @@ -624,7 +626,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { require(_tokenContract != address(0)); IERC20 token = IERC20(_tokenContract); uint256 balance = token.balanceOf(address(this)); - require(token.transfer(getAddress(Encoder.getKey("owner")), balance)); + require(token.transfer(owner(), balance)); } /** @@ -709,4 +711,12 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { return getBool(Encoder.getKey("paused")); } + /** + * @notice Gets the owner of the contract + * @return address owner + */ + function owner() public view returns(address) { + return getAddress(Encoder.getKey("owner")); + } + } diff --git a/contracts/interfaces/ISecurityTokenRegistry.sol b/contracts/interfaces/ISecurityTokenRegistry.sol index 5231e8ef4..2bacd39d7 100644 --- a/contracts/interfaces/ISecurityTokenRegistry.sol +++ b/contracts/interfaces/ISecurityTokenRegistry.sol @@ -181,6 +181,12 @@ interface ISecurityTokenRegistry { * @notice Check whether the registry is paused or not * @return bool */ - function isPaused() public view returns(bool); + function isPaused() external view returns(bool); + + /** + * @notice Gets the owner of the contract + * @return address owner + */ + function owner() external view returns(address); } From d56957feb37a17526705e36417b402c30af27493 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 14:33:25 +0100 Subject: [PATCH 13/19] Minor change --- contracts/SecurityTokenRegistry.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 926183238..9c4c059ef 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -196,7 +196,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { if (previousOwner != address(0)) { _deleteTickerOwnership(previousOwner, ticker); } - _addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, getTickerRegistrationFee()); + _addTicker(_owner, ticker, _tokenName, now, now.add(getExpiryLimit()), false, false, tickerFee); } /** @@ -488,7 +488,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { _storeSecurityTokenData(newSecurityTokenAddress, ticker, _tokenDetails, now); set(Encoder.getKey("tickerToSecurityToken", ticker), newSecurityTokenAddress); - emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false, getSecurityTokenLaunchFee()); + emit NewSecurityToken(ticker, _name, newSecurityTokenAddress, msg.sender, now, msg.sender, false, launchFee); } /** From 1420bce19088ec99464c091cbab15896a23b35b2 Mon Sep 17 00:00:00 2001 From: Victor Vicente Date: Mon, 1 Oct 2018 12:56:16 -0300 Subject: [PATCH 14/19] CLI: Owner getter on STR --- CLI/commands/contract_manager.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CLI/commands/contract_manager.js b/CLI/commands/contract_manager.js index 07d89d48e..594522f6f 100644 --- a/CLI/commands/contract_manager.js +++ b/CLI/commands/contract_manager.js @@ -13,8 +13,6 @@ var global = require('./common/global'); var contracts = require('./helpers/contract_addresses'); var abis = require('./helpers/contract_abis'); -const OWNER_KEY = 'owner'; - // App flow let currentContract = null; @@ -76,7 +74,7 @@ async function selectContract() { async function strActions() { console.log('\n\x1b[34m%s\x1b[0m',"Security Token Registry - Main menu"); - let contractOwner = await currentContract.methods.getAddressValues(web3.utils.soliditySha3(OWNER_KEY)).call(); + let contractOwner = await currentContract.methods.owner().call(); if (contractOwner != Issuer.address) { console.log(chalk.red(`You are not the owner of this contract. Current owner is ${contractOwner}`)); From 02d9426de8c9445e078c5ae449c8b3439c96a796 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 21:12:43 +0100 Subject: [PATCH 15/19] Fix --- contracts/SecurityTokenRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 9c4c059ef..606a82722 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -348,7 +348,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { assert(index < tickers.length); assert(_tickerOwner(_ticker) == _owner); deleteArrayBytes32(ownerKey, index); - if (tickers.length > index) { + if (getArrayBytes32(ownerKey).length > index) { bytes32 switchedTicker = tickers[index]; set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); } From 1c7ed17f3b5701e25fb8a19f42e88e5d92e32f1f Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 23:31:07 +0100 Subject: [PATCH 16/19] Fix modifyTicker --- contracts/SecurityTokenRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/SecurityTokenRegistry.sol b/contracts/SecurityTokenRegistry.sol index 606a82722..438e2eef5 100644 --- a/contracts/SecurityTokenRegistry.sol +++ b/contracts/SecurityTokenRegistry.sol @@ -349,7 +349,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage { assert(_tickerOwner(_ticker) == _owner); deleteArrayBytes32(ownerKey, index); if (getArrayBytes32(ownerKey).length > index) { - bytes32 switchedTicker = tickers[index]; + bytes32 switchedTicker = getArrayBytes32(ownerKey)[index]; set(Encoder.getKey("tickerIndex", Util.bytes32ToString(switchedTicker)), index); } } From 37b0b9674733da1405376a80a02fd0afe6fbcfc9 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 1 Oct 2018 23:36:52 +0100 Subject: [PATCH 17/19] Add more test cases --- test/n_security_token_registry.js | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/test/n_security_token_registry.js b/test/n_security_token_registry.js index 5b09d6160..f4ec3856f 100644 --- a/test/n_security_token_registry.js +++ b/test/n_security_token_registry.js @@ -1137,6 +1137,58 @@ contract('SecurityTokenRegistry', accounts => { }); }) + describe(" Test cases of the registerTicker", async() => { + + it("Should register the ticker 1", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK1", "", { 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, "TOK1", `Symbol should be TOK1`); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should register the ticker 2", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK2", "", { 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, "TOK2", `Symbol should be TOK2`); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should register the ticker 3", async () => { + await I_PolyToken.getTokens(web3.utils.toWei("1000"), account_temp); + await I_PolyToken.approve(I_STRProxied.address, web3.utils.toWei("1000"), { from: account_temp}); + let tx = await I_STRProxied.registerTicker(account_temp, "TOK3", "", { 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, "TOK3", `Symbol should be TOK3`); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should successfully remove the ticker 2", async() => { + let tx = await I_STRProxied.removeTicker("TOK2", {from: account_polymath}); + assert.equal(tx.logs[0].args._ticker, "TOK2", "Ticker doesn't get deleted successfully"); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }); + + it("Should modify ticker 1", async() => { + let tx = await I_STRProxied.modifyTicker(account_temp, "TOK1", "TOKEN 1", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); + assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK1", "Should be equal to TOK1"); + assert.equal(tx.logs[0].args._name, "TOKEN 1", "Should be equal to TOKEN 1"); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }) + + it("Should modify ticker 3", async() => { + let tx = await I_STRProxied.modifyTicker(account_temp, "TOK3", "TOKEN 3", latestTime(), (latestTime() + duration.minutes(10)), false, {from: account_polymath}); + assert.equal(tx.logs[0].args._owner, account_temp, `Should be equal to the ${account_temp}`); + assert.equal(tx.logs[0].args._ticker, "TOK3", "Should be equal to TOK3"); + assert.equal(tx.logs[0].args._name, "TOKEN 3", "Should be equal to TOKEN 3"); + console.log((await I_STRProxied.getTickersByOwner.call(account_temp)).map(x => web3.utils.toAscii(x))); + }) + + }); describe("Test cases for IRegistry functionality", async() => { describe("Test cases for reclaiming funds", async() => { From b666431903f3a1cb540da5ed723c1ad6bd274ce1 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 2 Oct 2018 11:39:18 +0100 Subject: [PATCH 18/19] Small fix --- contracts/tokens/SecurityToken.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index 6c866a7df..429114e10 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -667,6 +667,8 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr return true; } } + + return false; } /** From 6f0f44e171aeabfbe78e20755c72e2336304e102 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Tue, 2 Oct 2018 13:16:31 +0100 Subject: [PATCH 19/19] Fix bad merge --- contracts/tokens/SecurityToken.sol | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/contracts/tokens/SecurityToken.sol b/contracts/tokens/SecurityToken.sol index cdfde0d42..8d73a9e00 100644 --- a/contracts/tokens/SecurityToken.sol +++ b/contracts/tokens/SecurityToken.sol @@ -670,7 +670,7 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr return false; } - + function _burn(address _from, uint256 _value) internal returns (bool) { require(_value <= balances[_from], "Value too high"); require(_updateTransfer(_from, address(0), _value), "Burn is not valid"); @@ -715,27 +715,6 @@ contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, Registr return currentCheckpointId; } - /** - * @notice Validate permissions with PermissionManager if it exists, If no Permission return false - * @dev Note that IModule withPerm will allow ST owner all permissions anyway - * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions) - * @param _delegate address of delegate - * @param _module address of PermissionManager module - * @param _perm the permissions - * @return success - */ - function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) { - if (modules[PERMISSIONMANAGER_KEY].length == 0) { - return false; - } - - for (uint8 i = 0; i < modules[PERMISSIONMANAGER_KEY].length; i++) { - if (IPermissionManager(modules[PERMISSIONMANAGER_KEY][i]).checkPermission(_delegate, _module, _perm)) { - return true; - } - } - } - /** * @notice Gets list of times that checkpoints were created * @return List of checkpoint times