11pragma solidity ^ 0.4.24 ;
22
33import "openzeppelin-solidity/contracts/math/SafeMath.sol " ;
4- import "./interfaces/IOwner .sol " ;
4+ import "./interfaces/IOwnable .sol " ;
55import "./interfaces/ISTFactory.sol " ;
66import "./interfaces/IERC20.sol " ;
77import "./interfaces/ISecurityTokenRegistry.sol " ;
@@ -25,6 +25,9 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
2525 address public owner;
2626 address public polymathRegistry;
2727
28+ address[] public activeUsers;
29+ mapping(address => bool) public seenUsers;
30+
2831 mapping(address => bytes32[]) userToTickers;
2932 mapping(string => address) tickerToSecurityToken;
3033 mapping(string => uint) tickerIndex;
@@ -143,6 +146,11 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
143146 require (IERC20 (getAddress (Encoder.getKey ("polyToken " ))).transferFrom (msg .sender , address (this ), getUint (Encoder.getKey ("tickerRegFee " ))), "Sufficent allowance is not provided " );
144147 string memory ticker = Util.upper (_ticker);
145148 require (_tickerAvailable (ticker), "Ticker is already reserved " );
149+ // Check whether ticker was previously registered (and expired)
150+ address previousOwner = getAddress (Encoder.getKey ("registeredTickers_owner " , _ticker));
151+ if (previousOwner != address (0 )) {
152+ _deleteTickerOwnership (previousOwner, _ticker);
153+ }
146154 _addTicker (_owner, ticker, _tokenName, now , now .add (getUint (Encoder.getKey ("expiryLimit " ))), false , false );
147155 }
148156
@@ -232,6 +240,10 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
232240 uint256 length = uint256 (getArrayBytes32 (Encoder.getKey ("userToTickers " , _owner)).length );
233241 pushArray (Encoder.getKey ("userToTickers " , _owner), Util.stringToBytes32 (_ticker));
234242 set (Encoder.getKey ("tickerIndex " , _ticker), length);
243+ if (! getBool (Encoder.getKey ("seenUsers " , _owner))) {
244+ pushArray (Encoder.getKey ("activeUsers " ), _owner);
245+ set (Encoder.getKey ("seenUsers " , _owner), true );
246+ }
235247 }
236248
237249 /**
@@ -280,6 +292,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
280292 */
281293 function _deleteTickerOwnership (address _owner , string _ticker ) internal {
282294 uint256 _index = uint256 (getUint (Encoder.getKey ("tickerIndex " , _ticker)));
295+ assert (_index < getArrayBytes32 (Encoder.getKey ("userToTickers " , _owner)).length );
283296 // deleting the _index from the data strucutre userToTickers[_oldowner][_index];
284297 deleteArrayBytes32 (Encoder.getKey ("userToTickers " , _owner), _index);
285298
@@ -318,6 +331,48 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
318331 return tempList;
319332 }
320333
334+ /**
335+ * @notice Returns the list of tokens owned by the selected address
336+ * @param _owner is the address which owns the list of tickers
337+ * @dev Intention is that this is called off-chain so block gas limit is not relevant
338+ */
339+ function getTokensByOwner (address _owner ) external view returns (address []) {
340+ // Loop over all active users, then all associated tickers of those users
341+ // This ensures we find tokens, even if their owner has been modified
342+ address [] memory activeUsers = getArrayAddress (Encoder.getKey ("activeUsers " ));
343+ bytes32 [] memory tickers;
344+ address token;
345+ uint256 count = 0 ;
346+ uint256 i = 0 ;
347+ uint256 j = 0 ;
348+ for (i = 0 ; i < activeUsers.length ; i++ ) {
349+ tickers = getArrayBytes32 (Encoder.getKey ("userToTickers " , activeUsers[i]));
350+ for (j = 0 ; j < tickers.length ; j++ ) {
351+ token = getAddress (Encoder.getKey ("tickerToSecurityToken " , Util.bytes32ToString (tickers[j])));
352+ if (token != address (0 )) {
353+ if (IOwnable (token).owner () == _owner) {
354+ count = count + 1 ;
355+ }
356+ }
357+ }
358+ }
359+ uint256 index = 0 ;
360+ address [] memory result = new address [](count);
361+ for (i = 0 ; i < activeUsers.length ; i++ ) {
362+ tickers = getArrayBytes32 (Encoder.getKey ("userToTickers " , activeUsers[i]));
363+ for (j = 0 ; j < tickers.length ; j++ ) {
364+ token = getAddress (Encoder.getKey ("tickerToSecurityToken " , Util.bytes32ToString (tickers[j])));
365+ if (token != address (0 )) {
366+ if (IOwnable (token).owner () == _owner) {
367+ result[index] = token;
368+ index = index + 1 ;
369+ }
370+ }
371+ }
372+ }
373+ return result;
374+ }
375+
321376 /**
322377 * @notice Returns the owner and timestamp for a given ticker
323378 * @param _ticker is the ticker symbol
@@ -442,7 +497,7 @@ contract SecurityTokenRegistry is ISecurityTokenRegistry, EternalStorage {
442497 function getSecurityTokenData (address _securityToken ) external view returns (string , address , string , uint256 ) {
443498 return (
444499 getString (Encoder.getKey ("securityTokens_ticker " , _securityToken)),
445- IOwner (_securityToken).owner (),
500+ IOwnable (_securityToken).owner (),
446501 getString (Encoder.getKey ("securityTokens_tokenDetails " , _securityToken)),
447502 getUint (Encoder.getKey ("securityTokens_deployedAt " , _securityToken))
448503 );
0 commit comments