eth-token-index

Token symbol to address unique index
Log | Files | Refs

TokenUniqueSymbolIndex.sol (4795B)


      1 pragma solidity >=0.8.0;
      2 
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 
      5 contract TokenUniqueSymbolIndex {
      6 	mapping(address => bool) isWriter;
      7 	mapping ( bytes32 => uint256 ) registry;
      8 	mapping ( address => bytes32 ) tokenIndex;
      9 	address[] tokens;
     10 
     11 	// Implements EIP173
     12 	address public owner;
     13 
     14 	// Implements Registry
     15 	bytes32[] public identifierList;
     16 
     17 	// Implements EIP173
     18 	event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
     19 
     20 	// Implements AccountsIndex
     21 	event AddressKey(bytes32 indexed _symbol, address _token);
     22 
     23 	// Implements AccountsIndex
     24 	event AddressAdded(address _token);
     25 
     26 	// Implements AccountsIndexMutable
     27 	event AddressRemoved(address _token);
     28 
     29 	// Implements Writer
     30 	event WriterAdded(address _writer);
     31 
     32 	// Implements Writer
     33 	event WriterDeleted(address _writer);
     34 
     35 	constructor() {
     36 		owner = msg.sender;
     37 		tokens.push(address(0));
     38 		identifierList.push(bytes32(0));
     39 	}
     40 
     41 	// Implements AccountsIndex
     42 	function entry(uint256 _idx) public view returns ( address ) {
     43 		return tokens[_idx + 1];
     44 	}
     45 
     46 	// Implements RegistryClient
     47 	function addressOf(bytes32 _key) public view returns ( address ) {
     48 		uint256 idx;
     49 
     50 		idx = registry[_key];
     51 		return tokens[idx];
     52 	}
     53 
     54 	// Attempt to register the token at the given address.
     55 	// Will revet if symbol cannot be retrieved, or if symbol already exists.
     56 	function register(address _token) public returns (bool) {
     57 		require(isWriter[msg.sender]);
     58 
     59 		bytes memory token_symbol;
     60 		bytes32 token_symbol_key;
     61 		uint256 idx;
     62 
     63 		(bool _ok, bytes memory _r) = _token.call(abi.encodeWithSignature('symbol()'));
     64 		require(_ok);
     65 
     66 		token_symbol = abi.decode(_r, (bytes));
     67 		require(token_symbol.length <= 32, 'ERR_TOKEN_SYMBOL_TOO_LONG');
     68 		token_symbol_key = bytes32(token_symbol);
     69 
     70 		idx = registry[token_symbol_key];
     71 		require(idx == 0);
     72 
     73 		registry[token_symbol_key] = tokens.length;
     74 		tokens.push(_token);
     75 		identifierList.push(token_symbol_key);
     76 		tokenIndex[_token] = token_symbol_key;
     77 
     78 		emit AddressKey(token_symbol_key, _token);
     79 		emit AddressAdded(_token);
     80 		return true;
     81 	}
     82 
     83 	// Implements AccountsIndex
     84 	function add(address _token) public returns (bool) {
     85 		return register(_token);
     86 	}
     87 
     88 	// Implements AccountsIndex
     89 	function time(address _token) public pure returns(uint256) {
     90 		_token;
     91 		return 0;
     92 	}
     93 
     94 	// Implements AccountsIndexMutable
     95 	function remove(address _token) external returns (bool) {
     96 		uint256 i;
     97 		uint256 l;
     98 
     99 		require(isWriter[msg.sender] || msg.sender == owner, 'ERR_AXX');
    100 		require(tokenIndex[_token] != bytes32(0), 'ERR_NOT_FOUND');
    101 
    102 		l = tokens.length - 1;
    103 		i = registry[tokenIndex[_token]];
    104 		if (i < l) {
    105 			tokens[i] = tokens[l];
    106 			identifierList[i] = identifierList[l];
    107 		}
    108 		registry[tokenIndex[tokens[i]]] = i;
    109 		tokens.pop();
    110 		identifierList.pop();
    111 		registry[tokenIndex[_token]] = 0;
    112 		tokenIndex[_token] = bytes32(0);
    113 
    114 		emit AddressRemoved(_token);
    115 		return true;
    116 	}
    117 
    118 	// Implements AccountsIndexMutable
    119 	function activate(address _token) public pure returns(bool) {
    120 		_token;
    121 		return false;
    122 	}
    123 
    124 	// Implements AccountsIndexMutable
    125 	function deactivate(address _token) public pure returns(bool) {
    126 		_token;
    127 		return false;
    128 	}
    129 
    130 
    131 	// Implements AccountsIndex
    132 	function entryCount() public view returns ( uint256 ) {
    133 		return tokens.length - 1;
    134 	}
    135 
    136 	// Implements EIP173
    137 	function transferOwnership(address _newOwner) public returns (bool) {
    138 		address oldOwner;
    139 
    140 		require(msg.sender == owner);
    141 		oldOwner = owner;
    142 		owner = _newOwner;
    143 
    144 		emit OwnershipTransferred(oldOwner, owner);
    145 
    146 		return true;
    147 	}
    148 
    149 	// Implements Writer
    150 	function addWriter(address _writer) public returns (bool) {
    151 		require(owner == msg.sender);
    152 		isWriter[_writer] = true;
    153 
    154 		emit WriterAdded(_writer);
    155 
    156 		return true;
    157 	}
    158 
    159 	// Implements Writer
    160 	function deleteWriter(address _writer) public returns (bool) {
    161 		require(owner == msg.sender);
    162 		delete isWriter[_writer];
    163 
    164 		emit WriterDeleted(_writer);
    165 
    166 		return true;
    167 	}
    168 
    169 	// Implements Registry
    170 	function identifier(uint256 _idx) public view returns(bytes32) {
    171 		return identifierList[_idx + 1];
    172 	}
    173 
    174 	// Implements Registry
    175 	function identifierCount() public view returns(uint256) {
    176 		return identifierList.length - 1;
    177 	}
    178 
    179 	// Implements AccountsIndex	
    180 	function have(address _token) public view returns(bool) {
    181 		return tokenIndex[_token] != bytes32(0x0);
    182 	}
    183 
    184 	// Implements EIP165
    185 	function supportsInterface(bytes4 _sum) public pure returns (bool) {
    186 		if (_sum == 0xeffbf671) { // Registry
    187 			return true;
    188 		}
    189 		if (_sum == 0xb7bca625) { // AccountsIndex 
    190 			return true;
    191 		}
    192 		if (_sum == 0x9479f0ae) { // AccountsIndexMutable
    193 			return true;
    194 		}
    195 		if (_sum == 0x01ffc9a7) { // EIP165
    196 			return true;
    197 		}
    198 		if (_sum == 0x9493f8b2) { // EIP173
    199 			return true;
    200 		}
    201 		if (_sum == 0x80c84bd6) { // Writer
    202 			return true;
    203 		}
    204 		return false;
    205 	}
    206 }