AccountsIndex.sol (4377B)
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 isWriter; 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 isWriter[_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 isWriter[_writer]; 52 emit WriterDeleted(_writer); 53 return true; 54 } 55 56 // Implements AccountsIndex 57 function add(address _account) external returns (bool) { 58 uint256 i; 59 uint256 _entry; 60 61 require(isWriter[msg.sender]); 62 require(entryIndex[_account] == 0); 63 require(entryList.length < (1 << 64)); 64 i = entryList.length; 65 entryList.push(_account); 66 _entry = uint64(i); 67 _entry |= block.timestamp << 64; 68 entryIndex[_account] = _entry; 69 emit AddressAdded(_account); 70 return true; 71 } 72 73 // Implements AccountsIndexMutable 74 function remove(address _account) external returns (bool) { 75 uint256 i; 76 uint256 l; 77 78 require(isWriter[msg.sender], 'ERR_AXX'); 79 require(this.have(_account), 'ERR_ACL'); 80 81 l = entryList.length - 1; 82 83 i = entryIndex[_account]; 84 if (i < l) { 85 entryList[i] = entryList[l]; 86 } 87 entryList.pop(); 88 entryIndex[_account] = 0; 89 emit AddressRemoved(_account); 90 return true; 91 } 92 93 // Implements AccountsIndexMutable 94 function activate(address _account) external returns (bool) { 95 require(isWriter[msg.sender], 'ERR_AXX'); 96 require(entryIndex[_account] > 0, 'ERR_NOT_FOUND'); 97 require(entryIndex[_account] & blockedField == blockedField, 'ERR_NOT_BLOCKED'); 98 entryIndex[_account] >>= 129; 99 emit AddressActive(_account, true); 100 return true; 101 } 102 103 // Implements AccountsIndexMutable 104 function deactivate(address _account) external returns (bool) { 105 require(isWriter[msg.sender]); 106 require(entryIndex[_account] > 0, 'ERR_NOT_FOUND'); 107 require(entryIndex[_account] & blockedField == 0, 'ERR_NOT_ACTIVE'); 108 entryIndex[_account] <<= 129; 109 entryIndex[_account] |= blockedField; 110 emit AddressActive(_account, false); 111 return true; 112 } 113 114 // Implements AccountsIndex 115 function entry(uint256 _i) external view returns (address) { 116 return entryList[_i + 1]; 117 } 118 119 // Implements AccountsIndex 120 function time(address _account) external view returns (uint256) { 121 require(entryIndex[_account] > 0); 122 return entryIndex[_account] >> 64; 123 } 124 125 126 // Implements AccountsIndex 127 function have(address _account) external view returns (bool) { 128 return entryIndex[_account] > 0; 129 } 130 131 // Implements AccountsIndexMutable 132 function isActive(address _account) external view returns (bool) { 133 return this.have(_account) && entryIndex[_account] & blockedField != blockedField; 134 } 135 136 // Implements EIP173 137 function transferOwnership(address _newOwner) public returns (bool) { 138 address oldOwner; 139 require(msg.sender == owner, 'ERR_AXX'); 140 141 oldOwner = owner; 142 owner = _newOwner; 143 144 emit OwnershipTransferred(oldOwner, owner); 145 return true; 146 } 147 148 // Implements EIP165 149 function supportsInterface(bytes4 _sum) public pure returns (bool) { 150 if (_sum == 0xb7bca625) { // AccountsIndex 151 return true; 152 } 153 if (_sum == 0x9479f0ae) { // AccountsIndexMutable 154 return true; 155 } 156 if (_sum == 0x01ffc9a7) { // EIP165 157 return true; 158 } 159 if (_sum == 0x9493f8b2) { // EIP173 160 return true; 161 } 162 if (_sum == 0xabe1f1f5) { // Writer 163 return true; 164 } 165 return false; 166 } 167 }