AccountsIndex.sol (4512B)
1 pragma solidity >=0.8.0; 2 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // File-Version: 3 5 6 contract AccountsIndex { 7 uint256 constant blockedField = 1 << 128; 8 address[] entryList; 9 mapping(address => uint256) entryIndex; 10 11 // Implements Writer 12 mapping(address => bool) public writers; 13 14 // Implements ERC173 15 address public owner; 16 17 // Implements AccountsIndex 18 event AddressAdded(address _account); // AccountsIndex 19 // Implements AccountsIndexMutable 20 event AddressActive(address indexed _account, bool _active); 21 // Implements AccountsIndexMutable 22 event AddressRemoved(address _account); 23 // Implements ERC173 24 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // EIP173 25 // Implements Writer 26 event WriterAdded(address _account); // AccountsIndex 27 // Implements Writer 28 event WriterDeleted(address _account); 29 30 constructor() { 31 owner = msg.sender; 32 entryList.push(address(0)); 33 } 34 35 // Implements AccountsIndex 36 function entryCount() external view returns (uint256) { 37 return entryList.length - 1; 38 } 39 40 // Implements Writer 41 function addWriter(address _writer) public returns (bool) { 42 require(owner == msg.sender, 'ERR_AXX'); 43 writers[_writer] = true; 44 emit WriterAdded(_writer); 45 return true; 46 } 47 48 // Implements Writer 49 function deleteWriter(address _writer) public returns (bool) { 50 require(owner == msg.sender, 'ERR_AXX'); 51 delete writers[_writer]; 52 emit WriterDeleted(_writer); 53 return true; 54 } 55 56 // Implements Writer 57 function isWriter(address _writer) public view returns (bool) { 58 return writers[_writer] || _writer == owner; 59 } 60 61 // Implements AccountsIndex 62 function add(address _account) external returns (bool) { 63 uint256 i; 64 uint256 _entry; 65 66 require(isWriter(msg.sender)); 67 require(entryIndex[_account] == 0); 68 require(entryList.length < (1 << 64)); 69 i = entryList.length; 70 entryList.push(_account); 71 _entry = uint64(i); 72 _entry |= block.timestamp << 64; 73 entryIndex[_account] = _entry; 74 emit AddressAdded(_account); 75 return true; 76 } 77 78 // Implements AccountsIndexMutable 79 function remove(address _account) external returns (bool) { 80 uint256 i; 81 uint256 l; 82 83 require(isWriter(msg.sender), 'ERR_AXX'); 84 require(this.have(_account), 'ERR_ACL'); 85 86 l = entryList.length - 1; 87 88 i = entryIndex[_account]; 89 if (i < l) { 90 entryList[i] = entryList[l]; 91 } 92 entryList.pop(); 93 entryIndex[_account] = 0; 94 emit AddressRemoved(_account); 95 return true; 96 } 97 98 // Implements AccountsIndexMutable 99 function activate(address _account) external returns (bool) { 100 require(isWriter(msg.sender), 'ERR_AXX'); 101 require(entryIndex[_account] > 0, 'ERR_NOT_FOUND'); 102 require(entryIndex[_account] & blockedField == blockedField, 'ERR_NOT_BLOCKED'); 103 entryIndex[_account] >>= 129; 104 emit AddressActive(_account, true); 105 return true; 106 } 107 108 // Implements AccountsIndexMutable 109 function deactivate(address _account) external returns (bool) { 110 require(isWriter(msg.sender)); 111 require(entryIndex[_account] > 0, 'ERR_NOT_FOUND'); 112 require(entryIndex[_account] & blockedField == 0, 'ERR_NOT_ACTIVE'); 113 entryIndex[_account] <<= 129; 114 entryIndex[_account] |= blockedField; 115 emit AddressActive(_account, false); 116 return true; 117 } 118 119 // Implements AccountsIndex 120 function entry(uint256 _i) external view returns (address) { 121 return entryList[_i + 1]; 122 } 123 124 // Implements AccountsIndex 125 function time(address _account) external view returns (uint256) { 126 require(entryIndex[_account] > 0); 127 return entryIndex[_account] >> 64; 128 } 129 130 131 // Implements AccountsIndex 132 function have(address _account) external view returns (bool) { 133 return entryIndex[_account] > 0; 134 } 135 136 // Implements AccountsIndexMutable 137 function isActive(address _account) external view returns (bool) { 138 return this.have(_account) && entryIndex[_account] & blockedField != blockedField; 139 } 140 141 // Implements EIP173 142 function transferOwnership(address _newOwner) public returns (bool) { 143 address oldOwner; 144 require(msg.sender == owner, 'ERR_AXX'); 145 146 oldOwner = owner; 147 owner = _newOwner; 148 149 emit OwnershipTransferred(oldOwner, owner); 150 return true; 151 } 152 153 // Implements EIP165 154 function supportsInterface(bytes4 _sum) public pure returns (bool) { 155 if (_sum == 0xb7bca625) { // AccountsIndex 156 return true; 157 } 158 if (_sum == 0x9479f0ae) { // AccountsIndexMutable 159 return true; 160 } 161 if (_sum == 0x01ffc9a7) { // EIP165 162 return true; 163 } 164 if (_sum == 0x9493f8b2) { // EIP173 165 return true; 166 } 167 if (_sum == 0xabe1f1f5) { // Writer 168 return true; 169 } 170 return false; 171 } 172 }