github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/consensus/dpos/systemcontract/contracts/Validators.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity ^0.8.0;
     3  
     4  // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)
     5  /**
     6  
     7   * @dev Library for managing
     8  
     9   * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
    10  
    11   * types.
    12     *
    13  
    14   * Sets have the following properties:
    15     *
    16  
    17   * - Elements are added, removed, and checked for existence in constant time
    18  
    19   * (O(1)).
    20  
    21   * - Elements are enumerated in O(n). No guarantees are made on the ordering.
    22       *
    23  
    24   * ```
    25  
    26     ```
    27  
    28   * contract Example {
    29  
    30   * // Add the library methods
    31  
    32   * using EnumerableSet for EnumerableSet.AddressSet;
    33      *
    34  
    35   * // Declare a set state variable
    36  
    37   * EnumerableSet.AddressSet private mySet;
    38  
    39   * }
    40  
    41   * ```
    42     *
    43     ```
    44  
    45   * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
    46  
    47   * and `uint256` (`UintSet`) are supported.
    48     *
    49  
    50   * [WARNING]
    51  
    52   * ====
    53  
    54   * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
    55  
    56   * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
    57     *
    58  
    59   * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.
    60  
    61   * ====
    62     */
    63     library EnumerableSet {
    64     // To implement this library for multiple types with as little code
    65     // repetition as possible, we write it in terms of a generic Set type with
    66     // bytes32 values.
    67     // The Set implementation uses private functions, and user-facing
    68     // implementations (such as AddressSet) are just wrappers around the
    69     // underlying Set.
    70     // This means that we can only create new EnumerableSets for types that fit
    71     // in bytes32.
    72  
    73     struct Set {
    74         // Storage of set values
    75         bytes32[] _values;
    76         // Position of the value in the `values` array, plus 1 because index 0
    77         // means a value is not in the set.
    78         mapping(bytes32 => uint256) _indexes;
    79     }
    80  
    81     /**
    82  
    83      * @dev Add a value to a set. O(1).
    84        *
    85      * Returns true if the value was added to the set, that is if it was not
    86      * already present.
    87        */
    88        function _add(Set storage set, bytes32 value) private returns (bool) {
    89        if (!_contains(set, value)) {
    90            set._values.push(value);
    91            // The value is stored at length-1, but we add 1 to all indexes
    92            // and use 0 as a sentinel value
    93            set._indexes[value] = set._values.length;
    94            return true;
    95        } else {
    96            return false;
    97        }
    98        }
    99  
   100     /**
   101  
   102      * @dev Removes a value from a set. O(1).
   103        *
   104  
   105      * Returns true if the value was removed from the set, that is if it was
   106  
   107      * present.
   108        */
   109        function _remove(Set storage set, bytes32 value) private returns (bool) {
   110        // We read and store the value's index to prevent multiple reads from the same storage slot
   111        uint256 valueIndex = set._indexes[value];
   112  
   113        if (valueIndex != 0) {
   114            // Equivalent to contains(set, value)
   115            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
   116            // the array, and then remove the last element (sometimes called as 'swap and pop').
   117            // This modifies the order of the array, as noted in {at}.
   118  
   119            uint256 toDeleteIndex = valueIndex - 1;
   120            uint256 lastIndex = set._values.length - 1;
   121  
   122            if (lastIndex != toDeleteIndex) {
   123                bytes32 lastValue = set._values[lastIndex];
   124  
   125                // Move the last value to the index where the value to delete is
   126                set._values[toDeleteIndex] = lastValue;
   127                // Update the index for the moved value
   128                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
   129            }
   130  
   131            // Delete the slot where the moved value was stored
   132            set._values.pop();
   133  
   134            // Delete the index for the deleted slot
   135            delete set._indexes[value];
   136  
   137            return true;
   138  
   139        } else {
   140            return false;
   141        }
   142        }
   143  
   144     /**
   145  
   146      * @dev Returns true if the value is in the set. O(1).
   147        */
   148        function _contains(Set storage set, bytes32 value)
   149        private
   150        view
   151        returns (bool)
   152        {
   153        return set._indexes[value] != 0;
   154        }
   155  
   156     /**
   157  
   158      * @dev Returns the number of values on the set. O(1).
   159        */
   160        function _length(Set storage set) private view returns (uint256) {
   161        return set._values.length;
   162        }
   163  
   164     /**
   165  
   166      * @dev Returns the value stored at position `index` in the set. O(1).
   167        *
   168      * Note that there are no guarantees on the ordering of values inside the
   169      * array, and it may change when more values are added or removed.
   170        *
   171      * Requirements:
   172        *
   173      * - `index` must be strictly less than {length}.
   174          */
   175          function _at(Set storage set, uint256 index)
   176          private
   177          view
   178          returns (bytes32)
   179          {
   180          return set._values[index];
   181          }
   182  
   183     /**
   184  
   185      * @dev Return the entire set in an array
   186        *
   187      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   188      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   189      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   190      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   191        */
   192        function _values(Set storage set) private view returns (bytes32[] memory) {
   193        return set._values;
   194        }
   195  
   196     // Bytes32Set
   197  
   198     struct Bytes32Set {
   199         Set _inner;
   200     }
   201  
   202     /**
   203  
   204      * @dev Add a value to a set. O(1).
   205        *
   206      * Returns true if the value was added to the set, that is if it was not
   207      * already present.
   208        */
   209        function add(Bytes32Set storage set, bytes32 value)
   210        internal
   211        returns (bool)
   212        {
   213        return _add(set._inner, value);
   214        }
   215  
   216     /**
   217  
   218      * @dev Removes a value from a set. O(1).
   219        *
   220      * Returns true if the value was removed from the set, that is if it was
   221      * present.
   222        */
   223        function remove(Bytes32Set storage set, bytes32 value)
   224        internal
   225        returns (bool)
   226        {
   227        return _remove(set._inner, value);
   228        }
   229  
   230     /**
   231  
   232      * @dev Returns true if the value is in the set. O(1).
   233        */
   234        function contains(Bytes32Set storage set, bytes32 value)
   235        internal
   236        view
   237        returns (bool)
   238        {
   239        return _contains(set._inner, value);
   240        }
   241  
   242     /**
   243  
   244      * @dev Returns the number of values in the set. O(1).
   245        */
   246        function length(Bytes32Set storage set) internal view returns (uint256) {
   247        return _length(set._inner);
   248        }
   249  
   250     /**
   251  
   252      * @dev Returns the value stored at position `index` in the set. O(1).
   253        *
   254      * Note that there are no guarantees on the ordering of values inside the
   255      * array, and it may change when more values are added or removed.
   256        *
   257      * Requirements:
   258        *
   259      * - `index` must be strictly less than {length}.
   260          */
   261          function at(Bytes32Set storage set, uint256 index)
   262          internal
   263          view
   264          returns (bytes32)
   265          {
   266          return _at(set._inner, index);
   267          }
   268  
   269     /**
   270  
   271      * @dev Return the entire set in an array
   272        *
   273      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   274      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   275      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   276      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   277        */
   278        function values(Bytes32Set storage set)
   279        internal
   280        view
   281        returns (bytes32[] memory)
   282        {
   283        return _values(set._inner);
   284        }
   285  
   286     // AddressSet
   287  
   288     struct AddressSet {
   289         Set _inner;
   290     }
   291  
   292     /**
   293  
   294      * @dev Add a value to a set. O(1).
   295        *
   296      * Returns true if the value was added to the set, that is if it was not
   297      * already present.
   298        */
   299        function add(AddressSet storage set, address value)
   300        internal
   301        returns (bool)
   302        {
   303        return _add(set._inner, bytes32(uint256(uint160(value))));
   304        }
   305  
   306     /**
   307  
   308      * @dev Removes a value from a set. O(1).
   309        *
   310      * Returns true if the value was removed from the set, that is if it was
   311      * present.
   312        */
   313        function remove(AddressSet storage set, address value)
   314        internal
   315        returns (bool)
   316        {
   317        return _remove(set._inner, bytes32(uint256(uint160(value))));
   318        }
   319  
   320     /**
   321  
   322      * @dev Returns true if the value is in the set. O(1).
   323        */
   324        function contains(AddressSet storage set, address value)
   325        internal
   326        view
   327        returns (bool)
   328        {
   329        return _contains(set._inner, bytes32(uint256(uint160(value))));
   330        }
   331  
   332     /**
   333  
   334      * @dev Returns the number of values in the set. O(1).
   335        */
   336        function length(AddressSet storage set) internal view returns (uint256) {
   337        return _length(set._inner);
   338        }
   339  
   340     /**
   341  
   342      * @dev Returns the value stored at position `index` in the set. O(1).
   343        *
   344      * Note that there are no guarantees on the ordering of values inside the
   345      * array, and it may change when more values are added or removed.
   346        *
   347      * Requirements:
   348        *
   349      * - `index` must be strictly less than {length}.
   350          */
   351          function at(AddressSet storage set, uint256 index)
   352          internal
   353          view
   354          returns (address)
   355          {
   356          return address(uint160(uint256(_at(set._inner, index))));
   357          }
   358  
   359     /**
   360  
   361      * @dev Return the entire set in an array
   362        *
   363  
   364      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   365  
   366      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   367  
   368      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   369  
   370      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   371        */
   372        function values(AddressSet storage set)
   373        internal
   374        view
   375        returns (address[] memory)
   376        {
   377        bytes32[] memory store = _values(set._inner);
   378        address[] memory result;
   379  
   380        /// @solidity memory-safe-assembly
   381        assembly {
   382            result := store
   383        }
   384  
   385        return result;
   386        }
   387  
   388     // UintSet
   389  
   390     struct UintSet {
   391         Set _inner;
   392     }
   393  
   394     /**
   395  
   396      * @dev Add a value to a set. O(1).
   397        *
   398      * Returns true if the value was added to the set, that is if it was not
   399      * already present.
   400        */
   401        function add(UintSet storage set, uint256 value) internal returns (bool) {
   402        return _add(set._inner, bytes32(value));
   403        }
   404  
   405     /**
   406  
   407      * @dev Removes a value from a set. O(1).
   408        *
   409      * Returns true if the value was removed from the set, that is if it was
   410      * present.
   411        */
   412        function remove(UintSet storage set, uint256 value)
   413        internal
   414        returns (bool)
   415        {
   416        return _remove(set._inner, bytes32(value));
   417        }
   418  
   419     /**
   420  
   421      * @dev Returns true if the value is in the set. O(1).
   422        */
   423        function contains(UintSet storage set, uint256 value)
   424        internal
   425        view
   426        returns (bool)
   427        {
   428        return _contains(set._inner, bytes32(value));
   429        }
   430  
   431     /**
   432  
   433      * @dev Returns the number of values on the set. O(1).
   434        */
   435        function length(UintSet storage set) internal view returns (uint256) {
   436        return _length(set._inner);
   437        }
   438  
   439     /**
   440  
   441      * @dev Returns the value stored at position `index` in the set. O(1).
   442        *
   443      * Note that there are no guarantees on the ordering of values inside the
   444      * array, and it may change when more values are added or removed.
   445        *
   446      * Requirements:
   447        *
   448      * - `index` must be strictly less than {length}.
   449          */
   450          function at(UintSet storage set, uint256 index)
   451          internal
   452          view
   453          returns (uint256)
   454          {
   455          return uint256(_at(set._inner, index));
   456          }
   457  
   458     /**
   459  
   460      * @dev Return the entire set in an array
   461        *
   462  
   463      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   464  
   465      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   466  
   467      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   468  
   469      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   470        */
   471        function values(UintSet storage set)
   472        internal
   473        view
   474        returns (uint256[] memory)
   475        {
   476        bytes32[] memory store = _values(set._inner);
   477        uint256[] memory result;
   478  
   479        /// @solidity memory-safe-assembly
   480        assembly {
   481            result := store
   482        }
   483  
   484        return result;
   485        }
   486        }
   487  
   488  // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
   489  /**
   490  
   491   * @dev Collection of functions related to the address type
   492     */
   493     library Address {
   494     /**
   495  
   496      * @dev Returns true if `account` is a contract.
   497        *
   498  
   499      * [IMPORTANT]
   500  
   501      * ====
   502  
   503      * It is unsafe to assume that an address for which this function returns
   504  
   505      * false is an externally-owned account (EOA) and not a contract.
   506        *
   507  
   508      * Among others, `isContract` will return false for the following
   509  
   510      * types of addresses:
   511        *
   512  
   513      * - an externally-owned account
   514  
   515      * - a contract in construction
   516  
   517      * - an address where a contract will be created
   518  
   519      * - an address where a contract lived, but was destroyed
   520  
   521      * ====
   522        *
   523  
   524      * [IMPORTANT]
   525  
   526      * ====
   527  
   528      * You shouldn't rely on `isContract` to protect against flash loan attacks!
   529        *
   530  
   531      * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
   532  
   533      * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
   534  
   535      * constructor.
   536  
   537      * ====
   538        */
   539        function isContract(address account) internal view returns (bool) {
   540        // This method relies on extcodesize/address.code.length, which returns 0
   541        // for contracts in construction, since the code is only stored at the end
   542        // of the constructor execution.
   543  
   544        return account.code.length > 0;
   545        }
   546  
   547     /**
   548  
   549      * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
   550  
   551      * `recipient`, forwarding all available gas and reverting on errors.
   552        *
   553  
   554      * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
   555  
   556      * of certain opcodes, possibly making contracts go over the 2300 gas limit
   557  
   558      * imposed by `transfer`, making them unable to receive funds via
   559  
   560      * `transfer`. {sendValue} removes this limitation.
   561        *
   562  
   563      * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
   564        *
   565  
   566      * IMPORTANT: because control is transferred to `recipient`, care must be
   567  
   568      * taken to not create reentrancy vulnerabilities. Consider using
   569  
   570      * {ReentrancyGuard} or the
   571  
   572      * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
   573        */
   574        function sendValue(address payable recipient, uint256 amount) internal {
   575        require(
   576            address(this).balance >= amount,
   577            "Address: insufficient balance"
   578        );
   579  
   580        (bool success, ) = recipient.call{value: amount}("");
   581        require(
   582            success,
   583            "Address: unable to send value, recipient may have reverted"
   584        );
   585        }
   586  
   587     /**
   588  
   589      * @dev Performs a Solidity function call using a low level `call`. A
   590      * plain `call` is an unsafe replacement for a function call: use this
   591      * function instead.
   592        *
   593      * If `target` reverts with a revert reason, it is bubbled up by this
   594      * function (like regular Solidity function calls).
   595        *
   596      * Returns the raw returned data. To convert to the expected return value,
   597      * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
   598        *
   599      * Requirements:
   600        *
   601      * - `target` must be a contract.
   602      * - calling `target` with `data` must not revert.
   603          *
   604      * _Available since v3.1._
   605        */
   606        function functionCall(address target, bytes memory data)
   607        internal
   608        returns (bytes memory)
   609        {
   610        return functionCall(target, data, "Address: low-level call failed");
   611        }
   612  
   613     /**
   614  
   615      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
   616      * `errorMessage` as a fallback revert reason when `target` reverts.
   617        *
   618      * _Available since v3.1._
   619        */
   620        function functionCall(
   621        address target,
   622        bytes memory data,
   623        string memory errorMessage
   624        ) internal returns (bytes memory) {
   625        return functionCallWithValue(target, data, 0, errorMessage);
   626        }
   627  
   628     /**
   629  
   630      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   631      * but also transferring `value` wei to `target`.
   632        *
   633      * Requirements:
   634        *
   635      * - the calling contract must have an ETH balance of at least `value`.
   636      * - the called Solidity function must be `payable`.
   637          *
   638      * _Available since v3.1._
   639        */
   640        function functionCallWithValue(
   641        address target,
   642        bytes memory data,
   643        uint256 value
   644        ) internal returns (bytes memory) {
   645        return
   646            functionCallWithValue(
   647                target,
   648                data,
   649                value,
   650                "Address: low-level call with value failed"
   651            );
   652        }
   653  
   654     /**
   655  
   656      * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
   657  
   658      * with `errorMessage` as a fallback revert reason when `target` reverts.
   659        *
   660  
   661      * _Available since v3.1._
   662        */
   663        function functionCallWithValue(
   664        address target,
   665        bytes memory data,
   666        uint256 value,
   667        string memory errorMessage
   668        ) internal returns (bytes memory) {
   669        require(
   670            address(this).balance >= value,
   671            "Address: insufficient balance for call"
   672        );
   673        require(isContract(target), "Address: call to non-contract");
   674  
   675        (bool success, bytes memory returndata) = target.call{value: value}(
   676            data
   677        );
   678        return verifyCallResult(success, returndata, errorMessage);
   679        }
   680  
   681     /**
   682  
   683      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   684      * but performing a static call.
   685        *
   686      * _Available since v3.3._
   687        */
   688        function functionStaticCall(address target, bytes memory data)
   689        internal
   690        view
   691        returns (bytes memory)
   692        {
   693        return
   694            functionStaticCall(
   695                target,
   696                data,
   697                "Address: low-level static call failed"
   698            );
   699        }
   700  
   701     /**
   702  
   703      * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
   704  
   705      * but performing a static call.
   706        *
   707  
   708      * _Available since v3.3._
   709        */
   710        function functionStaticCall(
   711        address target,
   712        bytes memory data,
   713        string memory errorMessage
   714        ) internal view returns (bytes memory) {
   715        require(isContract(target), "Address: static call to non-contract");
   716  
   717        (bool success, bytes memory returndata) = target.staticcall(data);
   718        return verifyCallResult(success, returndata, errorMessage);
   719        }
   720  
   721     /**
   722  
   723      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   724      * but performing a delegate call.
   725        *
   726      * _Available since v3.4._
   727        */
   728        function functionDelegateCall(address target, bytes memory data)
   729        internal
   730        returns (bytes memory)
   731        {
   732        return
   733            functionDelegateCall(
   734                target,
   735                data,
   736                "Address: low-level delegate call failed"
   737            );
   738        }
   739  
   740     /**
   741  
   742      * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
   743  
   744      * but performing a delegate call.
   745        *
   746  
   747      * _Available since v3.4._
   748        */
   749        function functionDelegateCall(
   750        address target,
   751        bytes memory data,
   752        string memory errorMessage
   753        ) internal returns (bytes memory) {
   754        require(isContract(target), "Address: delegate call to non-contract");
   755  
   756        (bool success, bytes memory returndata) = target.delegatecall(data);
   757        return verifyCallResult(success, returndata, errorMessage);
   758        }
   759  
   760     /**
   761  
   762      * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
   763      * revert reason using the provided one.
   764        *
   765      * _Available since v4.3._
   766        */
   767        function verifyCallResult(
   768        bool success,
   769        bytes memory returndata,
   770        string memory errorMessage
   771        ) internal pure returns (bytes memory) {
   772        if (success) {
   773            return returndata;
   774        } else {
   775            // Look for revert reason and bubble it up if present
   776            if (returndata.length > 0) {
   777                // The easiest way to bubble the revert reason is using memory via assembly
   778                /// @solidity memory-safe-assembly
   779                assembly {
   780                    let returndata_size := mload(returndata)
   781                    revert(add(32, returndata), returndata_size)
   782                }
   783            } else {
   784                revert(errorMessage);
   785            }
   786        }
   787        }
   788        }
   789  
   790  // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
   791  /**
   792  
   793   * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
   794  
   795   * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
   796  
   797   * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
   798  
   799   * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
   800     *
   801  
   802   * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
   803  
   804   * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
   805  
   806   * case an upgrade adds a module that needs to be initialized.
   807     *
   808  
   809   * For example:
   810     *
   811  
   812   * [.hljs-theme-light.nopadding]
   813  
   814   * ```
   815  
   816     ```
   817  
   818   * contract MyToken is ERC20Upgradeable {
   819  
   820   * function initialize() initializer public {
   821  
   822   * __ERC20_init("MyToken", "MTK");
   823  
   824   * }
   825  
   826   * }
   827  
   828   * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
   829  
   830   * function initializeV2() reinitializer(2) public {
   831  
   832   * __ERC20Permit_init("MyToken");
   833  
   834   * }
   835  
   836   * }
   837  
   838   * ```
   839     *
   840     ```
   841  
   842   * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
   843  
   844   * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
   845     *
   846  
   847   * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
   848  
   849   * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
   850     *
   851  
   852   * [CAUTION]
   853  
   854   * ====
   855  
   856   * Avoid leaving a contract uninitialized.
   857     *
   858  
   859   * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
   860  
   861   * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
   862  
   863   * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
   864     *
   865  
   866   * [.hljs-theme-light.nopadding]
   867  
   868   * ```
   869  
   870     ```
   871  
   872   * /// @custom:oz-upgrades-unsafe-allow constructor
   873  
   874   * constructor() {
   875  
   876   * _disableInitializers();
   877  
   878   * }
   879  
   880   * ```
   881  
   882     ```
   883  
   884   * ====
   885     */
   886     abstract contract Initializable {
   887     /**
   888  
   889      * @dev Indicates that the contract has been initialized.
   890      * @custom:oz-retyped-from bool
   891        */
   892        uint8 private _initialized;
   893  
   894     /**
   895  
   896      * @dev Indicates that the contract is in the process of being initialized.
   897        */
   898        bool private _initializing;
   899  
   900     /**
   901  
   902      * @dev Triggered when the contract has been initialized or reinitialized.
   903        */
   904        event Initialized(uint8 version);
   905  
   906     /**
   907  
   908      * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
   909      * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
   910        */
   911        modifier initializer() {
   912        bool isTopLevelCall = !_initializing;
   913        require(
   914            (isTopLevelCall && _initialized < 1) ||
   915                (!Address.isContract(address(this)) && _initialized == 1),
   916            "Initializable: contract is already initialized"
   917        );
   918        _initialized = 1;
   919        if (isTopLevelCall) {
   920            _initializing = true;
   921        }
   922        _;
   923        if (isTopLevelCall) {
   924            _initializing = false;
   925            emit Initialized(1);
   926        }
   927        }
   928  
   929     /**
   930  
   931      * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
   932      * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
   933      * used to initialize parent contracts.
   934        *
   935      * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
   936      * initialization step. This is essential to configure modules that are added through upgrades and that require
   937      * initialization.
   938        *
   939      * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
   940      * a contract, executing them in the right order is up to the developer or operator.
   941        */
   942        modifier reinitializer(uint8 version) {
   943        require(
   944            !_initializing && _initialized < version,
   945            "Initializable: contract is already initialized"
   946        );
   947        _initialized = version;
   948        _initializing = true;
   949        _;
   950        _initializing = false;
   951        emit Initialized(version);
   952        }
   953  
   954     /**
   955  
   956      * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
   957      * {initializer} and {reinitializer} modifiers, directly or indirectly.
   958        */
   959        modifier onlyInitializing() {
   960        require(_initializing, "Initializable: contract is not initializing");
   961        _;
   962        }
   963  
   964     /**
   965  
   966      * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
   967      * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
   968      * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
   969      * through proxies.
   970        */
   971        function _disableInitializers() internal virtual {
   972        require(!_initializing, "Initializable: contract is initializing");
   973        if (_initialized < type(uint8).max) {
   974            _initialized = type(uint8).max;
   975            emit Initialized(type(uint8).max);
   976        }
   977        }
   978        }
   979  
   980  // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
   981  /**
   982  
   983   * @dev Contract module that helps prevent reentrant calls to a function.
   984     *
   985  
   986   * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
   987  
   988   * available, which can be applied to functions to make sure there are no nested
   989  
   990   * (reentrant) calls to them.
   991     *
   992  
   993   * Note that because there is a single `nonReentrant` guard, functions marked as
   994  
   995   * `nonReentrant` may not call one another. This can be worked around by making
   996  
   997   * those functions `private`, and then adding `external` `nonReentrant` entry
   998  
   999   * points to them.
  1000     *
  1001  
  1002   * TIP: If you would like to learn more about reentrancy and alternative ways
  1003  
  1004   * to protect against it, check out our blog post
  1005  
  1006   * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
  1007     */
  1008     abstract contract ReentrancyGuard {
  1009     // Booleans are more expensive than uint256 or any type that takes up a full
  1010     // word because each write operation emits an extra SLOAD to first read the
  1011     // slot's contents, replace the bits taken up by the boolean, and then write
  1012     // back. This is the compiler's defense against contract upgrades and
  1013     // pointer aliasing, and it cannot be disabled.
  1014  
  1015     // The values being non-zero value makes deployment a bit more expensive,
  1016     // but in exchange the refund on every call to nonReentrant will be lower in
  1017     // amount. Since refunds are capped to a percentage of the total
  1018     // transaction's gas, it is best to keep them low in cases like this one, to
  1019     // increase the likelihood of the full refund coming into effect.
  1020     uint256 private constant _NOT_ENTERED = 1;
  1021     uint256 private constant _ENTERED = 2;
  1022  
  1023     uint256 private _status;
  1024  
  1025     constructor() {
  1026         _status = _NOT_ENTERED;
  1027     }
  1028  
  1029     /**
  1030  
  1031      * @dev Prevents a contract from calling itself, directly or indirectly.
  1032  
  1033      * Calling a `nonReentrant` function from another `nonReentrant`
  1034  
  1035      * function is not supported. It is possible to prevent this from happening
  1036  
  1037      * by making the `nonReentrant` function external, and making it call a
  1038  
  1039      * `private` function that does the actual work.
  1040        */
  1041        modifier nonReentrant() {
  1042        // On the first call to nonReentrant, _notEntered will be true
  1043        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
  1044  
  1045        // Any calls to nonReentrant after this point will fail
  1046        _status = _ENTERED;
  1047  
  1048        _;
  1049  
  1050        // By storing the original value once again, a refund is triggered (see
  1051        // https://eips.ethereum.org/EIPS/eip-2200)
  1052        _status = _NOT_ENTERED;
  1053        }
  1054        }
  1055  
  1056  contract Base {
  1057      uint256 public constant BLOCK_SECONDS = 6;
  1058      /// @notice min rate. base on 100
  1059      uint8 public constant MIN_RATE = 70;
  1060      /// @notice max rate. base on 100
  1061      uint8 public constant MAX_RATE = 100;
  1062  
  1063      /// @notice 10 * 60 / BLOCK_SECONDS
  1064      uint256 public constant EPOCH_BLOCKS = 14400;
  1065      /// @notice min deposit for validator
  1066      uint256 public constant MIN_DEPOSIT = 4e7 ether;
  1067      uint256 public constant MAX_PUNISH_COUNT = 139;
  1068  
  1069      /// @notice use blocks as units in code: RATE_SET_LOCK_EPOCHS * EPOCH_BLOCKS
  1070      uint256 public constant RATE_SET_LOCK_EPOCHS = 1;
  1071      /// @notice use blocks as units in code: VALIDATOR_UNSTAKE_LOCK_EPOCHS * EPOCH_BLOCKS
  1072      uint256 public constant VALIDATOR_UNSTAKE_LOCK_EPOCHS = 1;
  1073      /// @notice use blocks as units in code: PROPOSAL_DURATION_EPOCHS * EPOCH_BLOCKS
  1074      uint256 public constant PROPOSAL_DURATION_EPOCHS = 7;
  1075      /// @notice use epoch as units in code: VALIDATOR_REWARD_LOCK_EPOCHS
  1076      uint256 public constant VALIDATOR_REWARD_LOCK_EPOCHS = 7;
  1077      /// @notice use epoch as units in code: VOTE_CANCEL_EPOCHS
  1078      uint256 public constant VOTE_CANCEL_EPOCHS = 1;
  1079  
  1080      uint256 public constant MAX_VALIDATORS_COUNT = 210;
  1081      uint256 public constant MAX_VALIDATOR_DETAIL_LENGTH = 1000;
  1082      uint256 public constant MAX_VALIDATOR_NAME_LENGTH = 100;
  1083  
  1084      // total deposit
  1085      uint256 public constant TOTAL_DEPOSIT_LV1 = 1e18 * 1e8 * 150;
  1086      uint256 public constant TOTAL_DEPOSIT_LV2 = 1e18 * 1e8 * 200;
  1087      uint256 public constant TOTAL_DEPOSIT_LV3 = 1e18 * 1e8 * 250;
  1088      uint256 public constant TOTAL_DEPOSIT_LV4 = 1e18 * 1e8 * 300;
  1089      uint256 public constant TOTAL_DEPOSIT_LV5 = 1e18 * 1e8 * 350;
  1090  
  1091      // block reward
  1092      uint256 public constant REWARD_DEPOSIT_UNDER_LV1 = 1e15 * 95250;
  1093      uint256 public constant REWARD_DEPOSIT_FROM_LV1_TO_LV2 = 1e15 * 128250;
  1094      uint256 public constant REWARD_DEPOSIT_FROM_LV2_TO_LV3 = 1e15 * 157125;
  1095      uint256 public constant REWARD_DEPOSIT_FROM_LV3_TO_LV4 = 1e15 * 180750;
  1096      uint256 public constant REWARD_DEPOSIT_FROM_LV4_TO_LV5 = 1e15 * 199875;
  1097      uint256 public constant REWARD_DEPOSIT_OVER_LV5 = 1e15 * 214125;
  1098  
  1099      // validator count
  1100      uint256 public constant MAX_VALIDATOR_COUNT_LV1 = 21;
  1101      uint256 public constant MAX_VALIDATOR_COUNT_LV2 = 33;
  1102      uint256 public constant MAX_VALIDATOR_COUNT_LV3 = 66;
  1103      uint256 public constant MAX_VALIDATOR_COUNT_LV4 = 99;
  1104      uint256 public constant MIN_LEVEL_VALIDATOR_COUNT = 60;
  1105      uint256 public constant MEDIUM_LEVEL_VALIDATOR_COUNT = 90;
  1106      uint256 public constant MAX_LEVEL_VALIDATOR_COUNT = 120;
  1107  
  1108      // dead address
  1109      address public constant BLACK_HOLE_ADDRESS =
  1110          0x0000000000000000000000000000000000000000;
  1111  
  1112      uint256 public constant SAFE_MULTIPLIER = 1e18;
  1113  
  1114      modifier onlySystem() {
  1115          require(tx.gasprice == 0, "Prohibit external calls");
  1116          _;
  1117      }
  1118  
  1119      modifier onlyMiner() {
  1120          require(msg.sender == block.coinbase, "msg.sender error");
  1121          _;
  1122      }
  1123  
  1124      /**
  1125       * @dev return current epoch
  1126       */
  1127      function currentEpoch() public view returns (uint256) {
  1128          return block.number / EPOCH_BLOCKS;
  1129      }
  1130  
  1131  }
  1132  
  1133  interface ISystemRewards {
  1134      function epochs(uint256 _epoch)
  1135          external
  1136          view
  1137          returns (
  1138              uint256,
  1139              uint256,
  1140              uint256,
  1141              uint256
  1142          );
  1143  
  1144      function updateValidatorWhileElect(
  1145          address _val,
  1146          uint8 _rate,
  1147          uint256 _newEpoch
  1148      ) external;
  1149  
  1150      function updateEpochWhileElect(
  1151          uint256 _tvl,
  1152          uint256 _valCount,
  1153          uint256 _effictiveValCount,
  1154          uint256 _newEpoch
  1155      ) external;
  1156  
  1157      function updateValidatorWhileEpochEnd(address _val, uint256 _votes)
  1158          external;
  1159  
  1160      function getRewardPerVote(address _val) external view returns (uint256);
  1161  
  1162  }
  1163  
  1164  interface IProposals {}
  1165  
  1166  interface INodeVote {
  1167      function totalVotes() external view returns (uint256);
  1168  }
  1169  
  1170  contract Validators is Base, Initializable, ReentrancyGuard {
  1171      using EnumerableSet for EnumerableSet.AddressSet;
  1172      using Address for address;
  1173  
  1174      enum ValidatorStatus {
  1175          canceled,
  1176          canceling,
  1177          cancelQueue,
  1178          kickout,
  1179          effictive
  1180      }
  1181  
  1182      address[] public curEpochValidators;
  1183      mapping(address => uint256) public curEpochValidatorsIdMap;
  1184  
  1185      EnumerableSet.AddressSet effictiveValidators;
  1186  
  1187      /// @notice canceled、canceling、kickout
  1188      EnumerableSet.AddressSet invalidValidators;
  1189  
  1190      struct Validator {
  1191          ValidatorStatus status;
  1192          uint256 deposit;
  1193          uint8 rate;
  1194          /// @notice name
  1195          string name;
  1196          /// @notice details
  1197          string details;
  1198          uint256 votes;
  1199          uint256 unstakeLockingEndBlock;
  1200          uint256 rateSettLockingEndBlock;
  1201      }
  1202  
  1203      mapping(address => Validator) _validators;
  1204  
  1205      mapping(address => EnumerableSet.AddressSet) validatorToVoters;
  1206  
  1207      /// @notice all validators deposit
  1208      uint256 public totalDeposit;
  1209  
  1210      /// @notice  cancel validator queue
  1211      EnumerableSet.AddressSet cancelingValidators;
  1212  
  1213      /// @notice SystemRewards contract
  1214      ISystemRewards public sysRewards;
  1215  
  1216      /// @notice Proposals contract
  1217      IProposals public proposals;
  1218  
  1219      /// @notice NodeVote contract
  1220      INodeVote public nodeVote;
  1221  
  1222      event LogAddValidator(
  1223          address indexed _val,
  1224          uint256 _deposit,
  1225          uint256 _rate
  1226      );
  1227      event LogUpdateValidatorDeposit(address indexed _val, uint256 _deposit);
  1228      event LogUpdateValidatorRate(
  1229          address indexed _val,
  1230          uint8 _preRate,
  1231          uint8 _rate
  1232      );
  1233      event LogUnstakeValidator(address indexed _val);
  1234      event LogRedeemValidator(address indexed _val);
  1235      event LogRestoreValidator(address indexed _val);
  1236  
  1237      /**
  1238       * @dev only Proposals contract address
  1239       */
  1240      modifier onlyProposalsC() {
  1241          require(
  1242              msg.sender == address(proposals),
  1243              "Validators: not Proposals contract address"
  1244          );
  1245          _;
  1246      }
  1247  
  1248      /**
  1249       * @dev only SystemRewards contract address
  1250       */
  1251      modifier onlySysRewardsC() {
  1252          require(
  1253              msg.sender == address(sysRewards),
  1254              "Validators: not SystemRewards contract address"
  1255          );
  1256          _;
  1257      }
  1258  
  1259      /**
  1260       * @dev only NodeVote contract address
  1261       */
  1262      modifier onlyNodeVoteC() {
  1263          require(
  1264              msg.sender == address(nodeVote),
  1265              "Validators: not NodeVote contract address"
  1266          );
  1267          _;
  1268      }
  1269  
  1270  
  1271      function initialize(
  1272          address _proposal,
  1273          address _sysReward,
  1274          address _nodeVote,
  1275          address _initVal,
  1276          uint256 _initDeposit,
  1277          uint8 _initRate,
  1278          string memory _name,
  1279          string memory _details
  1280      ) external payable onlySystem initializer {
  1281          sysRewards = ISystemRewards(_sysReward);
  1282          proposals = IProposals(_proposal);
  1283          nodeVote = INodeVote(_nodeVote);
  1284  
  1285          require(!_initVal.isContract(), "Validators: validator address error");
  1286          require(
  1287              msg.value == _initDeposit && _initDeposit >= MIN_DEPOSIT,
  1288              "Validators: deposit or value error"
  1289          );
  1290          require(
  1291              _initRate >= MIN_RATE && _initRate <= MAX_RATE,
  1292              "Validators: Rate must greater than MIN_RATE and less than MAX_RATE"
  1293          );
  1294  
  1295          Validator storage val = _validators[_initVal];
  1296          val.status = ValidatorStatus.effictive;
  1297          val.deposit = _initDeposit;
  1298          val.rate = _initRate;
  1299          val.name = _name;
  1300          val.details = _details;
  1301  
  1302          effictiveValidators.add(_initVal);
  1303          totalDeposit += _initDeposit;
  1304  
  1305          curEpochValidators.push(_initVal);
  1306          curEpochValidatorsIdMap[_initVal] = curEpochValidators.length;
  1307  
  1308          uint256 curEpoch = currentEpoch();
  1309          sysRewards.updateValidatorWhileElect(_initVal, _initRate, curEpoch);
  1310          sysRewards.updateEpochWhileElect(
  1311              totalDeposit,
  1312              curEpochValidators.length,
  1313              effictiveValidators.length(),
  1314              curEpoch
  1315          );
  1316  
  1317          emit LogAddValidator(_initVal, _initDeposit, _initRate);
  1318      }
  1319  
  1320      /**
  1321       * @dev get voter
  1322       */
  1323      function getValidatorVoters(
  1324          address _val,
  1325          uint256 page,
  1326          uint256 size
  1327      ) external view returns (address[] memory) {
  1328          require(page > 0 && size > 0, "Validators: Requests param error");
  1329          EnumerableSet.AddressSet storage voters = validatorToVoters[_val];
  1330          uint256 start = (page - 1) * size;
  1331          if (voters.length() < start) {
  1332              size = 0;
  1333          } else {
  1334              uint256 length = voters.length() - start;
  1335              if (length < size) {
  1336                  size = length;
  1337              }
  1338          }
  1339  
  1340          address[] memory vals = new address[](size);
  1341          for (uint256 i = 0; i < size; i++) {
  1342              vals[i] = voters.at(i + start);
  1343          }
  1344          return vals;
  1345      }
  1346  
  1347      /**
  1348       * @dev return voters count of validator
  1349       */
  1350      function validatorVotersLength(address _val) public view returns (uint256) {
  1351          return validatorToVoters[_val].length();
  1352      }
  1353  
  1354      /**
  1355       * @dev return validator info
  1356       */
  1357      function validators(address _val) external view returns (Validator memory) {
  1358          return _validators[_val];
  1359      }
  1360  
  1361      /**
  1362       * @dev batch query validator info
  1363       */
  1364      function batchValidators(address[] memory _vals)
  1365          external
  1366          view
  1367          returns (Validator[] memory)
  1368      {
  1369          uint256 len = _vals.length;
  1370          Validator[] memory valInfos = new Validator[](len);
  1371  
  1372          for (uint256 i = 0; i < len; i++) {
  1373              valInfos[i] = _validators[_vals[i]];
  1374          }
  1375          return valInfos;
  1376      }
  1377  
  1378      /**
  1379       * @dev return curEpochValidators
  1380       */
  1381      function getCurEpochValidators() external view returns (address[] memory) {
  1382          return curEpochValidators;
  1383      }
  1384  
  1385      /**
  1386       * @dev True: effictive
  1387       */
  1388      function isEffictiveValidator(address addr) external view returns (bool) {
  1389          return _validators[addr].status == ValidatorStatus.effictive;
  1390      }
  1391  
  1392      /**
  1393       * @dev return effictive Validators count
  1394       */
  1395      function effictiveValsLength() public view returns (uint256) {
  1396          return effictiveValidators.length();
  1397      }
  1398  
  1399      /**
  1400       * @dev return all effictive Validators
  1401       */
  1402      function getEffictiveValidators() public view returns (address[] memory) {
  1403          uint256 len = effictiveValidators.length();
  1404          address[] memory vals = new address[](len);
  1405  
  1406          for (uint256 i = 0; i < len; i++) {
  1407              vals[i] = effictiveValidators.at(i);
  1408          }
  1409          return vals;
  1410      }
  1411  
  1412      function getEffictiveValidatorsWithPage(uint256 page, uint256 size)
  1413          public
  1414          view
  1415          returns (address[] memory)
  1416      {
  1417          require(page > 0 && size > 0, "Validators: Requests param error");
  1418          uint256 len = effictiveValidators.length();
  1419          uint256 start = (page - 1) * size;
  1420          if (len < start) {
  1421              size = 0;
  1422          } else {
  1423              uint256 length = len - start;
  1424              if (length < size) {
  1425                  size = length;
  1426              }
  1427          }
  1428  
  1429          address[] memory vals = new address[](size);
  1430          for (uint256 i = 0; i < size; i++) {
  1431              vals[i] = effictiveValidators.at(i + start);
  1432          }
  1433          return vals;
  1434      }
  1435  
  1436      /**
  1437       * @dev return invalid Validators count
  1438       */
  1439      function invalidValsLength() public view returns (uint256) {
  1440          return invalidValidators.length();
  1441      }
  1442  
  1443      /**
  1444       * @dev return all invalid Validators
  1445       */
  1446      function getInvalidValidators() public view returns (address[] memory) {
  1447          uint256 len = invalidValidators.length();
  1448          address[] memory vals = new address[](len);
  1449  
  1450          for (uint256 i = 0; i < len; i++) {
  1451              vals[i] = invalidValidators.at(i);
  1452          }
  1453          return vals;
  1454      }
  1455  
  1456      function getInvalidValidatorsWithPage(uint256 page, uint256 size)
  1457          public
  1458          view
  1459          returns (address[] memory)
  1460      {
  1461          require(page > 0 && size > 0, "Validators: Requests param error");
  1462          uint256 len = invalidValidators.length();
  1463          uint256 start = (page - 1) * size;
  1464          if (len < start) {
  1465              size = 0;
  1466          } else {
  1467              uint256 length = len - start;
  1468              if (length < size) {
  1469                  size = length;
  1470              }
  1471          }
  1472  
  1473          address[] memory vals = new address[](size);
  1474          for (uint256 i = 0; i < size; i++) {
  1475              vals[i] = invalidValidators.at(i + start);
  1476          }
  1477          return vals;
  1478      }
  1479  
  1480      /**
  1481       * @dev return canceling validators count
  1482       */
  1483      function CancelQueueValidatorsLength() public view returns (uint256) {
  1484          return cancelingValidators.length();
  1485      }
  1486  
  1487      /**
  1488       * @dev return Cancel Queue Validators
  1489       */
  1490      function getCancelQueueValidators() public view returns (address[] memory) {
  1491          uint256 len = cancelingValidators.length();
  1492          address[] memory vals = new address[](len);
  1493  
  1494          for (uint256 i = 0; i < len; i++) {
  1495              vals[i] = cancelingValidators.at(i);
  1496          }
  1497          return vals;
  1498      }
  1499  
  1500      /**
  1501       * @dev update validator deposit
  1502       */
  1503      function updateValidatorDeposit(uint256 _deposit)
  1504          external
  1505          payable
  1506          nonReentrant
  1507      {
  1508          Validator storage val = _validators[msg.sender];
  1509          require(
  1510              val.status == ValidatorStatus.effictive,
  1511              "Validators: illegal msg.sender"
  1512          );
  1513          if (_deposit >= val.deposit) {
  1514              require(
  1515                  msg.value >= _deposit - val.deposit,
  1516                  "Validators: illegal deposit"
  1517              );
  1518              uint256 sub = _deposit - val.deposit;
  1519              totalDeposit += sub;
  1520              val.deposit = _deposit;
  1521              payable(msg.sender).transfer(msg.value - sub);
  1522          } else {
  1523              require(_deposit >= MIN_DEPOSIT, "Validators: illegal deposit");
  1524              uint256 sub = val.deposit - _deposit;
  1525              payable(msg.sender).transfer(sub);
  1526              val.deposit = _deposit;
  1527              totalDeposit -= sub;
  1528          }
  1529  
  1530          emit LogUpdateValidatorDeposit(msg.sender, val.deposit);
  1531      }
  1532  
  1533      /**
  1534       * @dev update validator rate
  1535       */
  1536      function updateValidatorRate(uint8 _rate) external nonReentrant {
  1537          Validator storage val = _validators[msg.sender];
  1538          require(
  1539              val.status == ValidatorStatus.effictive,
  1540              "Validators: illegal msg.sender"
  1541          );
  1542          require(
  1543              val.rateSettLockingEndBlock < block.number,
  1544              "Validators: illegal rate set block"
  1545          );
  1546          require(
  1547              _rate >= MIN_RATE && val.rate <= MAX_RATE,
  1548              "Validators: illegal Allocation ratio"
  1549          );
  1550          uint8 preRate = val.rate;
  1551          val.rate = _rate;
  1552          val.rateSettLockingEndBlock =
  1553              block.number +
  1554              RATE_SET_LOCK_EPOCHS *
  1555              EPOCH_BLOCKS;
  1556  
  1557          emit LogUpdateValidatorRate(msg.sender, preRate, _rate);
  1558      }
  1559  
  1560      /**
  1561       * @dev update validator name and details
  1562       */
  1563      function updateValidatorNameDetails(
  1564          string memory _name,
  1565          string memory _details
  1566      ) external nonReentrant {
  1567          Validator storage val = _validators[msg.sender];
  1568          require(
  1569              bytes(_details).length <= MAX_VALIDATOR_DETAIL_LENGTH,
  1570              "Validators: Details is too long"
  1571          );
  1572          require(
  1573              bytes(_name).length <= MAX_VALIDATOR_NAME_LENGTH,
  1574              "Validators: name is too long"
  1575          );
  1576          val.name = _name;
  1577          val.details = _details;
  1578      }
  1579  
  1580  
  1581      function addValidatorFromProposal(
  1582          address _val,
  1583          uint256 _deposit,
  1584          uint8 _rate,
  1585          string memory _name,
  1586          string memory _details
  1587      ) external payable onlyProposalsC {
  1588          require(!_val.isContract(), "Validators: validator address error");
  1589          require(
  1590              msg.value == _deposit,
  1591              "Validators: deposit not equal msg.value"
  1592          );
  1593  
  1594          Validator storage val = _validators[_val];
  1595          require(
  1596              val.status == ValidatorStatus.canceled,
  1597              "Validators: validator status error"
  1598          );
  1599  
  1600          val.status = ValidatorStatus.effictive;
  1601          val.deposit = _deposit;
  1602          val.rate = _rate;
  1603          val.name = _name;
  1604          val.details = _details;
  1605  
  1606          effictiveValidators.add(_val);
  1607          invalidValidators.remove(_val);
  1608          totalDeposit += _deposit;
  1609  
  1610          emit LogAddValidator(_val, _deposit, _rate);
  1611      }
  1612  
  1613  
  1614      function kickoutValidator(address _val) external onlySysRewardsC {
  1615          Validator storage val = _validators[_val];
  1616          require(
  1617              val.status == ValidatorStatus.effictive ||
  1618                  val.status == ValidatorStatus.kickout,
  1619              "Validators: validator status error"
  1620          );
  1621          val.status = ValidatorStatus.kickout;
  1622          if (effictiveValidators.contains(_val)) {
  1623              effictiveValidators.remove(_val);
  1624              invalidValidators.add(_val);
  1625              totalDeposit -= val.deposit;
  1626          }
  1627      }
  1628  
  1629      /**
  1630       * @dev restore validator from kickout status
  1631       */
  1632      function restore() external nonReentrant {
  1633          require(
  1634              effictiveValidators.length() < MAX_VALIDATORS_COUNT,
  1635              "Validators: length of the validator must be less than MAX_VALIDATORS_COUNT"
  1636          );
  1637          Validator storage val = _validators[msg.sender];
  1638          require(
  1639              !cancelingValidators.contains(msg.sender),
  1640              "Validators: this validator is canceling"
  1641          );
  1642          require(
  1643              val.status == ValidatorStatus.kickout,
  1644              "Validators: validator must be kickout"
  1645          );
  1646          val.status = ValidatorStatus.effictive;
  1647          effictiveValidators.add(msg.sender);
  1648          invalidValidators.remove(msg.sender);
  1649          totalDeposit += val.deposit;
  1650  
  1651          emit LogRestoreValidator(msg.sender);
  1652      }
  1653  
  1654  
  1655      function unstake() external nonReentrant {
  1656          Validator storage val = _validators[msg.sender];
  1657          require(
  1658              val.status == ValidatorStatus.effictive ||
  1659                  val.status == ValidatorStatus.kickout,
  1660              "Validators: illegal msg.sender"
  1661          );
  1662          if (curEpochValidatorsIdMap[msg.sender] == 0) {
  1663              cancelingValidators.remove(msg.sender);
  1664              val.status = ValidatorStatus.canceling;
  1665              val.unstakeLockingEndBlock =
  1666                  block.number +
  1667                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1668                  EPOCH_BLOCKS;
  1669  
  1670              if (effictiveValidators.contains(msg.sender)) {
  1671                  effictiveValidators.remove(msg.sender);
  1672                  invalidValidators.add(msg.sender);
  1673                  totalDeposit -= val.deposit;
  1674              }
  1675          } else {
  1676              val.status = ValidatorStatus.cancelQueue;
  1677              cancelingValidators.add(msg.sender);
  1678          }
  1679          emit LogUnstakeValidator(msg.sender);
  1680      }
  1681  
  1682  
  1683      function _cancelValidatorWhileElect() internal {
  1684          for (uint256 i = 0; i < cancelingValidators.length(); i++) {
  1685              address _val = cancelingValidators.at(0);
  1686  
  1687              Validator storage val = _validators[_val];
  1688              val.status = ValidatorStatus.canceling;
  1689              val.unstakeLockingEndBlock =
  1690                  block.number +
  1691                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1692                  EPOCH_BLOCKS;
  1693  
  1694              cancelingValidators.remove(_val);
  1695  
  1696              if (effictiveValidators.contains(_val)) {
  1697                  effictiveValidators.remove(_val);
  1698                  invalidValidators.add(_val);
  1699                  totalDeposit -= val.deposit;
  1700              }
  1701          }
  1702      }
  1703  
  1704  
  1705      function redeem() external nonReentrant {
  1706          Validator storage val = _validators[msg.sender];
  1707          require(
  1708              val.unstakeLockingEndBlock < block.number,
  1709              "Validators: illegal redeem block"
  1710          );
  1711          require(
  1712              val.status == ValidatorStatus.canceling &&
  1713                  curEpochValidatorsIdMap[msg.sender] == 0,
  1714              "Validators: illegal msg.sender"
  1715          );
  1716  
  1717          val.status = ValidatorStatus.canceled;
  1718          payable(msg.sender).transfer(val.deposit);
  1719          val.deposit = 0;
  1720          val.unstakeLockingEndBlock = 0;
  1721          val.rateSettLockingEndBlock = 0;
  1722          invalidValidators.remove(msg.sender);
  1723  
  1724          emit LogRedeemValidator(msg.sender);
  1725      }
  1726  
  1727  
  1728      function voteValidator(
  1729          address _voter,
  1730          address _val,
  1731          uint256 _votes
  1732      ) external payable onlyNodeVoteC {
  1733          _validators[_val].votes += _votes;
  1734          validatorToVoters[_val].add(_voter);
  1735      }
  1736  
  1737  
  1738      function cancelVoteValidator(
  1739          address _voter,
  1740          address _val,
  1741          uint256 _votes,
  1742          bool _clear
  1743      ) external onlyNodeVoteC {
  1744          _validators[_val].votes -= _votes;
  1745          if (_clear) {
  1746              validatorToVoters[_val].remove(_voter);
  1747          }
  1748      }
  1749  
  1750  
  1751      function tryElect() external onlySysRewardsC {
  1752          _cancelValidatorWhileElect();
  1753  
  1754          uint256 nextEpochValCount = nextEpochValidatorCount();
  1755          uint256 effictiveLen = effictiveValidators.length();
  1756  
  1757          for (uint256 i = 0; i < curEpochValidators.length; i++) {
  1758              address _val = curEpochValidators[i];
  1759              sysRewards.updateValidatorWhileEpochEnd(
  1760                  _val,
  1761                  _validators[_val].votes
  1762              );
  1763              delete curEpochValidatorsIdMap[_val];
  1764          }
  1765          delete curEpochValidators;
  1766  
  1767          uint256 total = 0;
  1768          for (uint256 i = 0; i < effictiveLen; i++) {
  1769              address val = effictiveValidators.at(i);
  1770              total += _validators[val].votes + _validators[val].deposit;
  1771          }
  1772  
  1773          uint256 totalTemp = total;
  1774          uint256 nextEpoch = currentEpoch() + 1;
  1775  
  1776          if (nextEpochValCount >= effictiveLen) {
  1777              for (uint256 i = 0; i < effictiveLen; i++) {
  1778                  address val = effictiveValidators.at(i);
  1779                  curEpochValidators.push(val);
  1780                  curEpochValidatorsIdMap[val] = curEpochValidators.length;
  1781                  sysRewards.updateValidatorWhileElect(
  1782                      val,
  1783                      _validators[val].rate,
  1784                      nextEpoch
  1785                  );
  1786              }
  1787          } else {
  1788              // for-loop tryElect
  1789              for (uint256 i = 0; i < nextEpochValCount; i++) {
  1790                  if (total <= 0) break;
  1791                  // get random number
  1792                  uint256 randDeposit = rand(total, i);
  1793  
  1794                  for (uint256 j = 0; j < effictiveLen; j++) {
  1795                      address val = effictiveValidators.at(j);
  1796                      if (curEpochValidatorsIdMap[val] != 0) continue;
  1797                      uint256 deposit = _validators[val].votes +
  1798                          _validators[val].deposit;
  1799                      if (randDeposit <= deposit) {
  1800                          curEpochValidators.push(val);
  1801                          curEpochValidatorsIdMap[val] = curEpochValidators
  1802                              .length;
  1803                          total -= deposit;
  1804                          sysRewards.updateValidatorWhileElect(
  1805                              val,
  1806                              _validators[val].rate,
  1807                              nextEpoch
  1808                          );
  1809                          break;
  1810                      }
  1811                      randDeposit -= deposit;
  1812                  }
  1813              }
  1814          }
  1815  
  1816          sysRewards.updateEpochWhileElect(
  1817              totalTemp,
  1818              curEpochValidators.length,
  1819              effictiveLen,
  1820              nextEpoch
  1821          );
  1822      }
  1823  
  1824  
  1825      function rand(uint256 _length, uint256 _i) internal view returns (uint256) {
  1826          uint256 random = uint256(
  1827              keccak256(abi.encodePacked(blockhash(block.number - _i - 1), _i))
  1828          );
  1829          return random % _length;
  1830      }
  1831  
  1832  
  1833      function recentFourteenEpochAvgValCount() internal view returns (uint256) {
  1834          uint256 curEpoch = currentEpoch();
  1835          if (curEpoch == 0) {
  1836              return effictiveValidators.length();
  1837          }
  1838          uint256 sumValidatorCount = 0;
  1839          uint256 avg = 14;
  1840          if (curEpoch < avg - 1) {
  1841              avg = curEpoch;
  1842          }
  1843          for (uint256 i = 0; i < avg; i++) {
  1844              (, , , uint256 effValCount) = sysRewards.epochs(curEpoch - i);
  1845              sumValidatorCount += effValCount;
  1846          }
  1847          return sumValidatorCount / avg;
  1848      }
  1849  
  1850  
  1851      function nextEpochValidatorCount() internal view returns (uint256) {
  1852          uint256 avgCount = recentFourteenEpochAvgValCount();
  1853          if (avgCount < MIN_LEVEL_VALIDATOR_COUNT) {
  1854              return MAX_VALIDATOR_COUNT_LV1;
  1855          }
  1856          if (avgCount < MEDIUM_LEVEL_VALIDATOR_COUNT) {
  1857              return MAX_VALIDATOR_COUNT_LV2;
  1858          }
  1859          if (avgCount < MAX_LEVEL_VALIDATOR_COUNT) {
  1860              return MAX_VALIDATOR_COUNT_LV3;
  1861          }
  1862          // avgCount >= MAX_LEVEL_VALIDATOR_COUNT
  1863          return MAX_VALIDATOR_COUNT_LV4;
  1864      }
  1865  
  1866  }