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

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity ^0.8.0;
     3  pragma abicoder v2;
     4  
     5  // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)
     6  /**
     7  
     8   * @dev Library for managing
     9  
    10   * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
    11  
    12   * types.
    13     *
    14  
    15   * Sets have the following properties:
    16     *
    17  
    18   * - Elements are added, removed, and checked for existence in constant time
    19  
    20   * (O(1)).
    21  
    22   * - Elements are enumerated in O(n). No guarantees are made on the ordering.
    23       *
    24  
    25   * ```
    26  
    27     ```
    28  
    29   * contract Example {
    30  
    31   * // Add the library methods
    32  
    33   * using EnumerableSet for EnumerableSet.AddressSet;
    34      *
    35  
    36   * // Declare a set state variable
    37  
    38   * EnumerableSet.AddressSet private mySet;
    39  
    40   * }
    41  
    42   * ```
    43     *
    44     ```
    45  
    46   * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
    47  
    48   * and `uint256` (`UintSet`) are supported.
    49     *
    50  
    51   * [WARNING]
    52  
    53   * ====
    54  
    55   * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
    56  
    57   * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
    58     *
    59  
    60   * 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.
    61  
    62   * ====
    63     */
    64     library EnumerableSet {
    65     // To implement this library for multiple types with as little code
    66     // repetition as possible, we write it in terms of a generic Set type with
    67     // bytes32 values.
    68     // The Set implementation uses private functions, and user-facing
    69     // implementations (such as AddressSet) are just wrappers around the
    70     // underlying Set.
    71     // This means that we can only create new EnumerableSets for types that fit
    72     // in bytes32.
    73  
    74     struct Set {
    75         // Storage of set values
    76         bytes32[] _values;
    77         // Position of the value in the `values` array, plus 1 because index 0
    78         // means a value is not in the set.
    79         mapping(bytes32 => uint256) _indexes;
    80     }
    81  
    82     /**
    83  
    84      * @dev Add a value to a set. O(1).
    85        *
    86      * Returns true if the value was added to the set, that is if it was not
    87      * already present.
    88        */
    89        function _add(Set storage set, bytes32 value) private returns (bool) {
    90        if (!_contains(set, value)) {
    91            set._values.push(value);
    92            // The value is stored at length-1, but we add 1 to all indexes
    93            // and use 0 as a sentinel value
    94            set._indexes[value] = set._values.length;
    95            return true;
    96        } else {
    97            return false;
    98        }
    99        }
   100  
   101     /**
   102  
   103      * @dev Removes a value from a set. O(1).
   104        *
   105  
   106      * Returns true if the value was removed from the set, that is if it was
   107  
   108      * present.
   109        */
   110        function _remove(Set storage set, bytes32 value) private returns (bool) {
   111        // We read and store the value's index to prevent multiple reads from the same storage slot
   112        uint256 valueIndex = set._indexes[value];
   113  
   114        if (valueIndex != 0) {
   115            // Equivalent to contains(set, value)
   116            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
   117            // the array, and then remove the last element (sometimes called as 'swap and pop').
   118            // This modifies the order of the array, as noted in {at}.
   119  
   120            uint256 toDeleteIndex = valueIndex - 1;
   121            uint256 lastIndex = set._values.length - 1;
   122  
   123            if (lastIndex != toDeleteIndex) {
   124                bytes32 lastValue = set._values[lastIndex];
   125  
   126                // Move the last value to the index where the value to delete is
   127                set._values[toDeleteIndex] = lastValue;
   128                // Update the index for the moved value
   129                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
   130            }
   131  
   132            // Delete the slot where the moved value was stored
   133            set._values.pop();
   134  
   135            // Delete the index for the deleted slot
   136            delete set._indexes[value];
   137  
   138            return true;
   139  
   140        } else {
   141            return false;
   142        }
   143        }
   144  
   145     /**
   146  
   147      * @dev Returns true if the value is in the set. O(1).
   148        */
   149        function _contains(Set storage set, bytes32 value)
   150        private
   151        view
   152        returns (bool)
   153        {
   154        return set._indexes[value] != 0;
   155        }
   156  
   157     /**
   158  
   159      * @dev Returns the number of values on the set. O(1).
   160        */
   161        function _length(Set storage set) private view returns (uint256) {
   162        return set._values.length;
   163        }
   164  
   165     /**
   166  
   167      * @dev Returns the value stored at position `index` in the set. O(1).
   168        *
   169      * Note that there are no guarantees on the ordering of values inside the
   170      * array, and it may change when more values are added or removed.
   171        *
   172      * Requirements:
   173        *
   174      * - `index` must be strictly less than {length}.
   175          */
   176          function _at(Set storage set, uint256 index)
   177          private
   178          view
   179          returns (bytes32)
   180          {
   181          return set._values[index];
   182          }
   183  
   184     /**
   185  
   186      * @dev Return the entire set in an array
   187        *
   188      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   189      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   190      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   191      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   192        */
   193        function _values(Set storage set) private view returns (bytes32[] memory) {
   194        return set._values;
   195        }
   196  
   197     // Bytes32Set
   198  
   199     struct Bytes32Set {
   200         Set _inner;
   201     }
   202  
   203     /**
   204  
   205      * @dev Add a value to a set. O(1).
   206        *
   207      * Returns true if the value was added to the set, that is if it was not
   208      * already present.
   209        */
   210        function add(Bytes32Set storage set, bytes32 value)
   211        internal
   212        returns (bool)
   213        {
   214        return _add(set._inner, value);
   215        }
   216  
   217     /**
   218  
   219      * @dev Removes a value from a set. O(1).
   220        *
   221      * Returns true if the value was removed from the set, that is if it was
   222      * present.
   223        */
   224        function remove(Bytes32Set storage set, bytes32 value)
   225        internal
   226        returns (bool)
   227        {
   228        return _remove(set._inner, value);
   229        }
   230  
   231     /**
   232  
   233      * @dev Returns true if the value is in the set. O(1).
   234        */
   235        function contains(Bytes32Set storage set, bytes32 value)
   236        internal
   237        view
   238        returns (bool)
   239        {
   240        return _contains(set._inner, value);
   241        }
   242  
   243     /**
   244  
   245      * @dev Returns the number of values in the set. O(1).
   246        */
   247        function length(Bytes32Set storage set) internal view returns (uint256) {
   248        return _length(set._inner);
   249        }
   250  
   251     /**
   252  
   253      * @dev Returns the value stored at position `index` in the set. O(1).
   254        *
   255      * Note that there are no guarantees on the ordering of values inside the
   256      * array, and it may change when more values are added or removed.
   257        *
   258      * Requirements:
   259        *
   260      * - `index` must be strictly less than {length}.
   261          */
   262          function at(Bytes32Set storage set, uint256 index)
   263          internal
   264          view
   265          returns (bytes32)
   266          {
   267          return _at(set._inner, index);
   268          }
   269  
   270     /**
   271  
   272      * @dev Return the entire set in an array
   273        *
   274      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   275      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   276      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   277      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   278        */
   279        function values(Bytes32Set storage set)
   280        internal
   281        view
   282        returns (bytes32[] memory)
   283        {
   284        return _values(set._inner);
   285        }
   286  
   287     // AddressSet
   288  
   289     struct AddressSet {
   290         Set _inner;
   291     }
   292  
   293     /**
   294  
   295      * @dev Add a value to a set. O(1).
   296        *
   297      * Returns true if the value was added to the set, that is if it was not
   298      * already present.
   299        */
   300        function add(AddressSet storage set, address value)
   301        internal
   302        returns (bool)
   303        {
   304        return _add(set._inner, bytes32(uint256(uint160(value))));
   305        }
   306  
   307     /**
   308  
   309      * @dev Removes a value from a set. O(1).
   310        *
   311      * Returns true if the value was removed from the set, that is if it was
   312      * present.
   313        */
   314        function remove(AddressSet storage set, address value)
   315        internal
   316        returns (bool)
   317        {
   318        return _remove(set._inner, bytes32(uint256(uint160(value))));
   319        }
   320  
   321     /**
   322  
   323      * @dev Returns true if the value is in the set. O(1).
   324        */
   325        function contains(AddressSet storage set, address value)
   326        internal
   327        view
   328        returns (bool)
   329        {
   330        return _contains(set._inner, bytes32(uint256(uint160(value))));
   331        }
   332  
   333     /**
   334  
   335      * @dev Returns the number of values in the set. O(1).
   336        */
   337        function length(AddressSet storage set) internal view returns (uint256) {
   338        return _length(set._inner);
   339        }
   340  
   341     /**
   342  
   343      * @dev Returns the value stored at position `index` in the set. O(1).
   344        *
   345      * Note that there are no guarantees on the ordering of values inside the
   346      * array, and it may change when more values are added or removed.
   347        *
   348      * Requirements:
   349        *
   350      * - `index` must be strictly less than {length}.
   351          */
   352          function at(AddressSet storage set, uint256 index)
   353          internal
   354          view
   355          returns (address)
   356          {
   357          return address(uint160(uint256(_at(set._inner, index))));
   358          }
   359  
   360     /**
   361  
   362      * @dev Return the entire set in an array
   363        *
   364  
   365      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   366  
   367      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   368  
   369      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   370  
   371      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   372        */
   373        function values(AddressSet storage set)
   374        internal
   375        view
   376        returns (address[] memory)
   377        {
   378        bytes32[] memory store = _values(set._inner);
   379        address[] memory result;
   380  
   381        /// @solidity memory-safe-assembly
   382        assembly {
   383            result := store
   384        }
   385  
   386        return result;
   387        }
   388  
   389     // UintSet
   390  
   391     struct UintSet {
   392         Set _inner;
   393     }
   394  
   395     /**
   396  
   397      * @dev Add a value to a set. O(1).
   398        *
   399      * Returns true if the value was added to the set, that is if it was not
   400      * already present.
   401        */
   402        function add(UintSet storage set, uint256 value) internal returns (bool) {
   403        return _add(set._inner, bytes32(value));
   404        }
   405  
   406     /**
   407  
   408      * @dev Removes a value from a set. O(1).
   409        *
   410      * Returns true if the value was removed from the set, that is if it was
   411      * present.
   412        */
   413        function remove(UintSet storage set, uint256 value)
   414        internal
   415        returns (bool)
   416        {
   417        return _remove(set._inner, bytes32(value));
   418        }
   419  
   420     /**
   421  
   422      * @dev Returns true if the value is in the set. O(1).
   423        */
   424        function contains(UintSet storage set, uint256 value)
   425        internal
   426        view
   427        returns (bool)
   428        {
   429        return _contains(set._inner, bytes32(value));
   430        }
   431  
   432     /**
   433  
   434      * @dev Returns the number of values on the set. O(1).
   435        */
   436        function length(UintSet storage set) internal view returns (uint256) {
   437        return _length(set._inner);
   438        }
   439  
   440     /**
   441  
   442      * @dev Returns the value stored at position `index` in the set. O(1).
   443        *
   444      * Note that there are no guarantees on the ordering of values inside the
   445      * array, and it may change when more values are added or removed.
   446        *
   447      * Requirements:
   448        *
   449      * - `index` must be strictly less than {length}.
   450          */
   451          function at(UintSet storage set, uint256 index)
   452          internal
   453          view
   454          returns (uint256)
   455          {
   456          return uint256(_at(set._inner, index));
   457          }
   458  
   459     /**
   460  
   461      * @dev Return the entire set in an array
   462        *
   463  
   464      * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
   465  
   466      * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
   467  
   468      * this function has an unbounded cost, and using it as part of a state-changing function may render the function
   469  
   470      * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
   471        */
   472        function values(UintSet storage set)
   473        internal
   474        view
   475        returns (uint256[] memory)
   476        {
   477        bytes32[] memory store = _values(set._inner);
   478        uint256[] memory result;
   479  
   480        /// @solidity memory-safe-assembly
   481        assembly {
   482            result := store
   483        }
   484  
   485        return result;
   486        }
   487        }
   488  
   489  // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
   490  /**
   491  
   492   * @dev Collection of functions related to the address type
   493     */
   494     library Address {
   495     /**
   496  
   497      * @dev Returns true if `account` is a contract.
   498        *
   499  
   500      * [IMPORTANT]
   501  
   502      * ====
   503  
   504      * It is unsafe to assume that an address for which this function returns
   505  
   506      * false is an externally-owned account (EOA) and not a contract.
   507        *
   508  
   509      * Among others, `isContract` will return false for the following
   510  
   511      * types of addresses:
   512        *
   513  
   514      * - an externally-owned account
   515  
   516      * - a contract in construction
   517  
   518      * - an address where a contract will be created
   519  
   520      * - an address where a contract lived, but was destroyed
   521  
   522      * ====
   523        *
   524  
   525      * [IMPORTANT]
   526  
   527      * ====
   528  
   529      * You shouldn't rely on `isContract` to protect against flash loan attacks!
   530        *
   531  
   532      * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
   533  
   534      * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
   535  
   536      * constructor.
   537  
   538      * ====
   539        */
   540        function isContract(address account) internal view returns (bool) {
   541        // This method relies on extcodesize/address.code.length, which returns 0
   542        // for contracts in construction, since the code is only stored at the end
   543        // of the constructor execution.
   544  
   545        return account.code.length > 0;
   546        }
   547  
   548     /**
   549  
   550      * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
   551  
   552      * `recipient`, forwarding all available gas and reverting on errors.
   553        *
   554  
   555      * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
   556  
   557      * of certain opcodes, possibly making contracts go over the 2300 gas limit
   558  
   559      * imposed by `transfer`, making them unable to receive funds via
   560  
   561      * `transfer`. {sendValue} removes this limitation.
   562        *
   563  
   564      * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
   565        *
   566  
   567      * IMPORTANT: because control is transferred to `recipient`, care must be
   568  
   569      * taken to not create reentrancy vulnerabilities. Consider using
   570  
   571      * {ReentrancyGuard} or the
   572  
   573      * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
   574        */
   575        function sendValue(address payable recipient, uint256 amount) internal {
   576        require(
   577            address(this).balance >= amount,
   578            "Address: insufficient balance"
   579        );
   580  
   581        (bool success, ) = recipient.call{value: amount}("");
   582        require(
   583            success,
   584            "Address: unable to send value, recipient may have reverted"
   585        );
   586        }
   587  
   588     /**
   589  
   590      * @dev Performs a Solidity function call using a low level `call`. A
   591      * plain `call` is an unsafe replacement for a function call: use this
   592      * function instead.
   593        *
   594      * If `target` reverts with a revert reason, it is bubbled up by this
   595      * function (like regular Solidity function calls).
   596        *
   597      * Returns the raw returned data. To convert to the expected return value,
   598      * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
   599        *
   600      * Requirements:
   601        *
   602      * - `target` must be a contract.
   603      * - calling `target` with `data` must not revert.
   604          *
   605      * _Available since v3.1._
   606        */
   607        function functionCall(address target, bytes memory data)
   608        internal
   609        returns (bytes memory)
   610        {
   611        return functionCall(target, data, "Address: low-level call failed");
   612        }
   613  
   614     /**
   615  
   616      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
   617      * `errorMessage` as a fallback revert reason when `target` reverts.
   618        *
   619      * _Available since v3.1._
   620        */
   621        function functionCall(
   622        address target,
   623        bytes memory data,
   624        string memory errorMessage
   625        ) internal returns (bytes memory) {
   626        return functionCallWithValue(target, data, 0, errorMessage);
   627        }
   628  
   629     /**
   630  
   631      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   632      * but also transferring `value` wei to `target`.
   633        *
   634      * Requirements:
   635        *
   636      * - the calling contract must have an ETH balance of at least `value`.
   637      * - the called Solidity function must be `payable`.
   638          *
   639      * _Available since v3.1._
   640        */
   641        function functionCallWithValue(
   642        address target,
   643        bytes memory data,
   644        uint256 value
   645        ) internal returns (bytes memory) {
   646        return
   647            functionCallWithValue(
   648                target,
   649                data,
   650                value,
   651                "Address: low-level call with value failed"
   652            );
   653        }
   654  
   655     /**
   656  
   657      * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
   658  
   659      * with `errorMessage` as a fallback revert reason when `target` reverts.
   660        *
   661  
   662      * _Available since v3.1._
   663        */
   664        function functionCallWithValue(
   665        address target,
   666        bytes memory data,
   667        uint256 value,
   668        string memory errorMessage
   669        ) internal returns (bytes memory) {
   670        require(
   671            address(this).balance >= value,
   672            "Address: insufficient balance for call"
   673        );
   674        require(isContract(target), "Address: call to non-contract");
   675  
   676        (bool success, bytes memory returndata) = target.call{value: value}(
   677            data
   678        );
   679        return verifyCallResult(success, returndata, errorMessage);
   680        }
   681  
   682     /**
   683  
   684      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   685      * but performing a static call.
   686        *
   687      * _Available since v3.3._
   688        */
   689        function functionStaticCall(address target, bytes memory data)
   690        internal
   691        view
   692        returns (bytes memory)
   693        {
   694        return
   695            functionStaticCall(
   696                target,
   697                data,
   698                "Address: low-level static call failed"
   699            );
   700        }
   701  
   702     /**
   703  
   704      * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
   705  
   706      * but performing a static call.
   707        *
   708  
   709      * _Available since v3.3._
   710        */
   711        function functionStaticCall(
   712        address target,
   713        bytes memory data,
   714        string memory errorMessage
   715        ) internal view returns (bytes memory) {
   716        require(isContract(target), "Address: static call to non-contract");
   717  
   718        (bool success, bytes memory returndata) = target.staticcall(data);
   719        return verifyCallResult(success, returndata, errorMessage);
   720        }
   721  
   722     /**
   723  
   724      * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
   725      * but performing a delegate call.
   726        *
   727      * _Available since v3.4._
   728        */
   729        function functionDelegateCall(address target, bytes memory data)
   730        internal
   731        returns (bytes memory)
   732        {
   733        return
   734            functionDelegateCall(
   735                target,
   736                data,
   737                "Address: low-level delegate call failed"
   738            );
   739        }
   740  
   741     /**
   742  
   743      * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
   744  
   745      * but performing a delegate call.
   746        *
   747  
   748      * _Available since v3.4._
   749        */
   750        function functionDelegateCall(
   751        address target,
   752        bytes memory data,
   753        string memory errorMessage
   754        ) internal returns (bytes memory) {
   755        require(isContract(target), "Address: delegate call to non-contract");
   756  
   757        (bool success, bytes memory returndata) = target.delegatecall(data);
   758        return verifyCallResult(success, returndata, errorMessage);
   759        }
   760  
   761     /**
   762  
   763      * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
   764      * revert reason using the provided one.
   765        *
   766      * _Available since v4.3._
   767        */
   768        function verifyCallResult(
   769        bool success,
   770        bytes memory returndata,
   771        string memory errorMessage
   772        ) internal pure returns (bytes memory) {
   773        if (success) {
   774            return returndata;
   775        } else {
   776            // Look for revert reason and bubble it up if present
   777            if (returndata.length > 0) {
   778                // The easiest way to bubble the revert reason is using memory via assembly
   779                /// @solidity memory-safe-assembly
   780                assembly {
   781                    let returndata_size := mload(returndata)
   782                    revert(add(32, returndata), returndata_size)
   783                }
   784            } else {
   785                revert(errorMessage);
   786            }
   787        }
   788        }
   789        }
   790  
   791  // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
   792  /**
   793  
   794   * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
   795  
   796   * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
   797  
   798   * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
   799  
   800   * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
   801     *
   802  
   803   * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
   804  
   805   * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
   806  
   807   * case an upgrade adds a module that needs to be initialized.
   808     *
   809  
   810   * For example:
   811     *
   812  
   813   * [.hljs-theme-light.nopadding]
   814  
   815   * ```
   816  
   817     ```
   818  
   819   * contract MyToken is ERC20Upgradeable {
   820  
   821   * function initialize() initializer public {
   822  
   823   * __ERC20_init("MyToken", "MTK");
   824  
   825   * }
   826  
   827   * }
   828  
   829   * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
   830  
   831   * function initializeV2() reinitializer(2) public {
   832  
   833   * __ERC20Permit_init("MyToken");
   834  
   835   * }
   836  
   837   * }
   838  
   839   * ```
   840     *
   841     ```
   842  
   843   * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
   844  
   845   * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
   846     *
   847  
   848   * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
   849  
   850   * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
   851     *
   852  
   853   * [CAUTION]
   854  
   855   * ====
   856  
   857   * Avoid leaving a contract uninitialized.
   858     *
   859  
   860   * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
   861  
   862   * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
   863  
   864   * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
   865     *
   866  
   867   * [.hljs-theme-light.nopadding]
   868  
   869   * ```
   870  
   871     ```
   872  
   873   * /// @custom:oz-upgrades-unsafe-allow constructor
   874  
   875   * constructor() {
   876  
   877   * _disableInitializers();
   878  
   879   * }
   880  
   881   * ```
   882  
   883     ```
   884  
   885   * ====
   886     */
   887     abstract contract Initializable {
   888     /**
   889  
   890      * @dev Indicates that the contract has been initialized.
   891      * @custom:oz-retyped-from bool
   892        */
   893        uint8 private _initialized;
   894  
   895     /**
   896  
   897      * @dev Indicates that the contract is in the process of being initialized.
   898        */
   899        bool private _initializing;
   900  
   901     /**
   902  
   903      * @dev Triggered when the contract has been initialized or reinitialized.
   904        */
   905        event Initialized(uint8 version);
   906  
   907     /**
   908  
   909      * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
   910      * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
   911        */
   912        modifier initializer() {
   913        bool isTopLevelCall = !_initializing;
   914        require(
   915            (isTopLevelCall && _initialized < 1) ||
   916                (!Address.isContract(address(this)) && _initialized == 1),
   917            "Initializable: contract is already initialized"
   918        );
   919        _initialized = 1;
   920        if (isTopLevelCall) {
   921            _initializing = true;
   922        }
   923        _;
   924        if (isTopLevelCall) {
   925            _initializing = false;
   926            emit Initialized(1);
   927        }
   928        }
   929  
   930     /**
   931  
   932      * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
   933      * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
   934      * used to initialize parent contracts.
   935        *
   936      * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
   937      * initialization step. This is essential to configure modules that are added through upgrades and that require
   938      * initialization.
   939        *
   940      * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
   941      * a contract, executing them in the right order is up to the developer or operator.
   942        */
   943        modifier reinitializer(uint8 version) {
   944        require(
   945            !_initializing && _initialized < version,
   946            "Initializable: contract is already initialized"
   947        );
   948        _initialized = version;
   949        _initializing = true;
   950        _;
   951        _initializing = false;
   952        emit Initialized(version);
   953        }
   954  
   955     /**
   956  
   957      * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
   958      * {initializer} and {reinitializer} modifiers, directly or indirectly.
   959        */
   960        modifier onlyInitializing() {
   961        require(_initializing, "Initializable: contract is not initializing");
   962        _;
   963        }
   964  
   965     /**
   966  
   967      * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
   968      * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
   969      * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
   970      * through proxies.
   971        */
   972        function _disableInitializers() internal virtual {
   973        require(!_initializing, "Initializable: contract is initializing");
   974        if (_initialized < type(uint8).max) {
   975            _initialized = type(uint8).max;
   976            emit Initialized(type(uint8).max);
   977        }
   978        }
   979        }
   980  
   981  // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
   982  /**
   983  
   984   * @dev Contract module that helps prevent reentrant calls to a function.
   985     *
   986  
   987   * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
   988  
   989   * available, which can be applied to functions to make sure there are no nested
   990  
   991   * (reentrant) calls to them.
   992     *
   993  
   994   * Note that because there is a single `nonReentrant` guard, functions marked as
   995  
   996   * `nonReentrant` may not call one another. This can be worked around by making
   997  
   998   * those functions `private`, and then adding `external` `nonReentrant` entry
   999  
  1000   * points to them.
  1001     *
  1002  
  1003   * TIP: If you would like to learn more about reentrancy and alternative ways
  1004  
  1005   * to protect against it, check out our blog post
  1006  
  1007   * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
  1008     */
  1009     abstract contract ReentrancyGuard {
  1010     // Booleans are more expensive than uint256 or any type that takes up a full
  1011     // word because each write operation emits an extra SLOAD to first read the
  1012     // slot's contents, replace the bits taken up by the boolean, and then write
  1013     // back. This is the compiler's defense against contract upgrades and
  1014     // pointer aliasing, and it cannot be disabled.
  1015  
  1016     // The values being non-zero value makes deployment a bit more expensive,
  1017     // but in exchange the refund on every call to nonReentrant will be lower in
  1018     // amount. Since refunds are capped to a percentage of the total
  1019     // transaction's gas, it is best to keep them low in cases like this one, to
  1020     // increase the likelihood of the full refund coming into effect.
  1021     uint256 private constant _NOT_ENTERED = 1;
  1022     uint256 private constant _ENTERED = 2;
  1023  
  1024     uint256 private _status;
  1025  
  1026     constructor() {
  1027         _status = _NOT_ENTERED;
  1028     }
  1029  
  1030     /**
  1031  
  1032      * @dev Prevents a contract from calling itself, directly or indirectly.
  1033  
  1034      * Calling a `nonReentrant` function from another `nonReentrant`
  1035  
  1036      * function is not supported. It is possible to prevent this from happening
  1037  
  1038      * by making the `nonReentrant` function external, and making it call a
  1039  
  1040      * `private` function that does the actual work.
  1041        */
  1042        modifier nonReentrant() {
  1043        // On the first call to nonReentrant, _notEntered will be true
  1044        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
  1045  
  1046        // Any calls to nonReentrant after this point will fail
  1047        _status = _ENTERED;
  1048  
  1049        _;
  1050  
  1051        // By storing the original value once again, a refund is triggered (see
  1052        // https://eips.ethereum.org/EIPS/eip-2200)
  1053        _status = _NOT_ENTERED;
  1054        }
  1055        }
  1056  
  1057  contract Base {
  1058      uint256 public constant BLOCK_SECONDS = 6;
  1059      /// @notice min rate. base on 100
  1060      uint8 public constant MIN_RATE = 70;
  1061      /// @notice max rate. base on 100
  1062      uint8 public constant MAX_RATE = 100;
  1063  
  1064      /// @notice 10 * 60 / BLOCK_SECONDS
  1065      uint256 public constant EPOCH_BLOCKS = 14400;
  1066      /// @notice min deposit for validator
  1067      uint256 public constant MIN_DEPOSIT = 4e7 ether;
  1068      uint256 public constant MAX_PUNISH_COUNT = 139;
  1069  
  1070      /// @notice use blocks as units in code: RATE_SET_LOCK_EPOCHS * EPOCH_BLOCKS
  1071      uint256 public constant RATE_SET_LOCK_EPOCHS = 1;
  1072      /// @notice use blocks as units in code: VALIDATOR_UNSTAKE_LOCK_EPOCHS * EPOCH_BLOCKS
  1073      uint256 public constant VALIDATOR_UNSTAKE_LOCK_EPOCHS = 1;
  1074      /// @notice use blocks as units in code: PROPOSAL_DURATION_EPOCHS * EPOCH_BLOCKS
  1075      uint256 public constant PROPOSAL_DURATION_EPOCHS = 7;
  1076      /// @notice use epoch as units in code: VALIDATOR_REWARD_LOCK_EPOCHS
  1077      uint256 public constant VALIDATOR_REWARD_LOCK_EPOCHS = 7;
  1078      /// @notice use epoch as units in code: VOTE_CANCEL_EPOCHS
  1079      uint256 public constant VOTE_CANCEL_EPOCHS = 1;
  1080  
  1081      uint256 public constant MAX_VALIDATORS_COUNT = 210;
  1082      uint256 public constant MAX_VALIDATOR_DETAIL_LENGTH = 1000;
  1083      uint256 public constant MAX_VALIDATOR_NAME_LENGTH = 100;
  1084  
  1085      // total deposit
  1086      uint256 public constant TOTAL_DEPOSIT_LV1 = 1e18 * 1e8 * 150;
  1087      uint256 public constant TOTAL_DEPOSIT_LV2 = 1e18 * 1e8 * 200;
  1088      uint256 public constant TOTAL_DEPOSIT_LV3 = 1e18 * 1e8 * 250;
  1089      uint256 public constant TOTAL_DEPOSIT_LV4 = 1e18 * 1e8 * 300;
  1090      uint256 public constant TOTAL_DEPOSIT_LV5 = 1e18 * 1e8 * 350;
  1091  
  1092      // block reward
  1093      uint256 public constant REWARD_DEPOSIT_UNDER_LV1 = 1e15 * 95250;
  1094      uint256 public constant REWARD_DEPOSIT_FROM_LV1_TO_LV2 = 1e15 * 128250;
  1095      uint256 public constant REWARD_DEPOSIT_FROM_LV2_TO_LV3 = 1e15 * 157125;
  1096      uint256 public constant REWARD_DEPOSIT_FROM_LV3_TO_LV4 = 1e15 * 180750;
  1097      uint256 public constant REWARD_DEPOSIT_FROM_LV4_TO_LV5 = 1e15 * 199875;
  1098      uint256 public constant REWARD_DEPOSIT_OVER_LV5 = 1e15 * 214125;
  1099  
  1100      // validator count
  1101      uint256 public constant MAX_VALIDATOR_COUNT_LV1 = 21;
  1102      uint256 public constant MAX_VALIDATOR_COUNT_LV2 = 33;
  1103      uint256 public constant MAX_VALIDATOR_COUNT_LV3 = 66;
  1104      uint256 public constant MAX_VALIDATOR_COUNT_LV4 = 99;
  1105      uint256 public constant MIN_LEVEL_VALIDATOR_COUNT = 60;
  1106      uint256 public constant MEDIUM_LEVEL_VALIDATOR_COUNT = 90;
  1107      uint256 public constant MAX_LEVEL_VALIDATOR_COUNT = 120;
  1108  
  1109      // dead address
  1110      address public constant BLACK_HOLE_ADDRESS =
  1111          0x0000000000000000000000000000000000000000;
  1112  
  1113      uint256 public constant SAFE_MULTIPLIER = 1e18;
  1114  
  1115      modifier onlySystem() {
  1116          require(tx.gasprice == 0, "Prohibit external calls");
  1117          _;
  1118      }
  1119  
  1120      modifier onlyMiner() {
  1121          require(msg.sender == block.coinbase, "msg.sender error");
  1122          _;
  1123      }
  1124  
  1125      /**
  1126       * @dev return current epoch
  1127       */
  1128      function currentEpoch() public view returns (uint256) {
  1129          return block.number / EPOCH_BLOCKS;
  1130      }
  1131  
  1132  }
  1133  
  1134  interface ISystemRewards {
  1135      function epochs(uint256 _epoch)
  1136          external
  1137          view
  1138          returns (
  1139              uint256,
  1140              uint256,
  1141              uint256,
  1142              uint256
  1143          );
  1144  
  1145      function updateValidatorWhileElect(
  1146          address _val,
  1147          uint8 _rate,
  1148          uint256 _newEpoch
  1149      ) external;
  1150  
  1151      function updateEpochWhileElect(
  1152          uint256 _tvl,
  1153          uint256 _valCount,
  1154          uint256 _effictiveValCount,
  1155          uint256 _newEpoch
  1156      ) external;
  1157  
  1158      function updateValidatorWhileEpochEnd(address _val, uint256 _votes)
  1159          external;
  1160  
  1161      function getRewardPerVote(address _val) external view returns (uint256);
  1162  
  1163  }
  1164  
  1165  interface IProposals {}
  1166  
  1167  interface INodeVote {
  1168      function totalVotes() external view returns (uint256);
  1169  }
  1170  
  1171  contract Validators is Base, Initializable, ReentrancyGuard {
  1172      using EnumerableSet for EnumerableSet.AddressSet;
  1173      using Address for address;
  1174  
  1175      enum ValidatorStatus {
  1176          canceled,
  1177          canceling,
  1178          cancelQueue,
  1179          kickout,
  1180          effictive
  1181      }
  1182  
  1183      address[] public curEpochValidators;
  1184      mapping(address => uint256) public curEpochValidatorsIdMap;
  1185  
  1186      EnumerableSet.AddressSet effictiveValidators;
  1187  
  1188      /// @notice canceled、canceling、kickout
  1189      EnumerableSet.AddressSet invalidValidators;
  1190  
  1191      struct Validator {
  1192          ValidatorStatus status;
  1193          uint256 deposit;
  1194          uint8 rate;
  1195          /// @notice name
  1196          string name;
  1197          /// @notice details
  1198          string details;
  1199          uint256 votes;
  1200          uint256 unstakeLockingEndBlock;
  1201          uint256 rateSettLockingEndBlock;
  1202      }
  1203  
  1204      mapping(address => Validator) _validators;
  1205  
  1206      mapping(address => EnumerableSet.AddressSet) validatorToVoters;
  1207  
  1208      /// @notice all validators deposit
  1209      uint256 public totalDeposit;
  1210  
  1211      /// @notice  cancel validator queue
  1212      EnumerableSet.AddressSet cancelingValidators;
  1213  
  1214      /// @notice SystemRewards contract
  1215      ISystemRewards public sysRewards;
  1216  
  1217      /// @notice Proposals contract
  1218      IProposals public proposals;
  1219  
  1220      /// @notice NodeVote contract
  1221      INodeVote public nodeVote;
  1222  
  1223      event LogAddValidator(
  1224          address indexed _val,
  1225          uint256 _deposit,
  1226          uint256 _rate
  1227      );
  1228      event LogUpdateValidatorDeposit(address indexed _val, uint256 _deposit);
  1229      event LogUpdateValidatorRate(
  1230          address indexed _val,
  1231          uint8 _preRate,
  1232          uint8 _rate
  1233      );
  1234      event LogUnstakeValidator(address indexed _val);
  1235      event LogRedeemValidator(address indexed _val);
  1236      event LogRestoreValidator(address indexed _val);
  1237  
  1238      /**
  1239       * @dev only Proposals contract address
  1240       */
  1241      modifier onlyProposalsC() {
  1242          require(
  1243              msg.sender == address(proposals),
  1244              "Validators: not Proposals contract address"
  1245          );
  1246          _;
  1247      }
  1248  
  1249      /**
  1250       * @dev only SystemRewards contract address
  1251       */
  1252      modifier onlySysRewardsC() {
  1253          require(
  1254              msg.sender == address(sysRewards),
  1255              "Validators: not SystemRewards contract address"
  1256          );
  1257          _;
  1258      }
  1259  
  1260      /**
  1261       * @dev only NodeVote contract address
  1262       */
  1263      modifier onlyNodeVoteC() {
  1264          require(
  1265              msg.sender == address(nodeVote),
  1266              "Validators: not NodeVote contract address"
  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      function addValidatorFromProposal(
  1581          address _val,
  1582          uint256 _deposit,
  1583          uint8 _rate,
  1584          string memory _name,
  1585          string memory _details
  1586      ) external payable onlyProposalsC {
  1587          require(!_val.isContract(), "Validators: validator address error");
  1588          require(
  1589              msg.value == _deposit,
  1590              "Validators: deposit not equal msg.value"
  1591          );
  1592  
  1593          Validator storage val = _validators[_val];
  1594          require(
  1595              val.status == ValidatorStatus.canceled,
  1596              "Validators: validator status error"
  1597          );
  1598  
  1599          val.status = ValidatorStatus.effictive;
  1600          val.deposit = _deposit;
  1601          val.rate = _rate;
  1602          val.name = _name;
  1603          val.details = _details;
  1604  
  1605          effictiveValidators.add(_val);
  1606          invalidValidators.remove(_val);
  1607          totalDeposit += _deposit;
  1608  
  1609          emit LogAddValidator(_val, _deposit, _rate);
  1610      }
  1611  
  1612      function kickoutValidator(address _val) external onlySysRewardsC {
  1613          Validator storage val = _validators[_val];
  1614          require(
  1615              val.status == ValidatorStatus.effictive ||
  1616                  val.status == ValidatorStatus.kickout,
  1617              "Validators: validator status error"
  1618          );
  1619          val.status = ValidatorStatus.kickout;
  1620          if (effictiveValidators.contains(_val)) {
  1621              effictiveValidators.remove(_val);
  1622              invalidValidators.add(_val);
  1623              totalDeposit -= val.deposit;
  1624          }
  1625      }
  1626  
  1627      /**
  1628       * @dev restore validator from kickout status
  1629       */
  1630      function restore() external nonReentrant {
  1631          require(
  1632              effictiveValidators.length() < MAX_VALIDATORS_COUNT,
  1633              "Validators: length of the validator must be less than MAX_VALIDATORS_COUNT"
  1634          );
  1635          Validator storage val = _validators[msg.sender];
  1636          require(
  1637              !cancelingValidators.contains(msg.sender),
  1638              "Validators: this validator is canceling"
  1639          );
  1640          require(
  1641              val.status == ValidatorStatus.kickout,
  1642              "Validators: validator must be kickout"
  1643          );
  1644          val.status = ValidatorStatus.effictive;
  1645          effictiveValidators.add(msg.sender);
  1646          invalidValidators.remove(msg.sender);
  1647          totalDeposit += val.deposit;
  1648  
  1649          emit LogRestoreValidator(msg.sender);
  1650      }
  1651  
  1652      function unstake() external nonReentrant {
  1653          Validator storage val = _validators[msg.sender];
  1654          require(
  1655              val.status == ValidatorStatus.effictive ||
  1656                  val.status == ValidatorStatus.kickout,
  1657              "Validators: illegal msg.sender"
  1658          );
  1659          if (curEpochValidatorsIdMap[msg.sender] == 0) {
  1660              cancelingValidators.remove(msg.sender);
  1661              val.status = ValidatorStatus.canceling;
  1662              val.unstakeLockingEndBlock =
  1663                  block.number +
  1664                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1665                  EPOCH_BLOCKS;
  1666  
  1667              if (effictiveValidators.contains(msg.sender)) {
  1668                  effictiveValidators.remove(msg.sender);
  1669                  invalidValidators.add(msg.sender);
  1670                  totalDeposit -= val.deposit;
  1671              }
  1672          } else {
  1673              val.status = ValidatorStatus.cancelQueue;
  1674              cancelingValidators.add(msg.sender);
  1675          }
  1676          emit LogUnstakeValidator(msg.sender);
  1677      }
  1678  
  1679      function _cancelValidatorWhileElect() internal {
  1680          for (uint256 i = 0; i < cancelingValidators.length(); i++) {
  1681              address _val = cancelingValidators.at(0);
  1682  
  1683              Validator storage val = _validators[_val];
  1684              val.status = ValidatorStatus.canceling;
  1685              val.unstakeLockingEndBlock =
  1686                  block.number +
  1687                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1688                  EPOCH_BLOCKS;
  1689  
  1690              cancelingValidators.remove(_val);
  1691  
  1692              if (effictiveValidators.contains(_val)) {
  1693                  effictiveValidators.remove(_val);
  1694                  invalidValidators.add(_val);
  1695                  totalDeposit -= val.deposit;
  1696              }
  1697          }
  1698      }
  1699  
  1700      function redeem() external nonReentrant {
  1701          Validator storage val = _validators[msg.sender];
  1702          require(
  1703              val.unstakeLockingEndBlock < block.number,
  1704              "Validators: illegal redeem block"
  1705          );
  1706          require(
  1707              val.status == ValidatorStatus.canceling &&
  1708                  curEpochValidatorsIdMap[msg.sender] == 0,
  1709              "Validators: illegal msg.sender"
  1710          );
  1711  
  1712          val.status = ValidatorStatus.canceled;
  1713          payable(msg.sender).transfer(val.deposit);
  1714          val.deposit = 0;
  1715          val.unstakeLockingEndBlock = 0;
  1716          val.rateSettLockingEndBlock = 0;
  1717          invalidValidators.remove(msg.sender);
  1718  
  1719          emit LogRedeemValidator(msg.sender);
  1720      }
  1721  
  1722      function voteValidator(
  1723          address _voter,
  1724          address _val,
  1725          uint256 _votes
  1726      ) external payable onlyNodeVoteC {
  1727          _validators[_val].votes += _votes;
  1728          validatorToVoters[_val].add(_voter);
  1729      }
  1730  
  1731      function cancelVoteValidator(
  1732          address _voter,
  1733          address _val,
  1734          uint256 _votes,
  1735          bool _clear
  1736      ) external onlyNodeVoteC {
  1737          _validators[_val].votes -= _votes;
  1738          if (_clear) {
  1739              validatorToVoters[_val].remove(_voter);
  1740          }
  1741      }
  1742  
  1743      function tryElect() external onlySysRewardsC {
  1744          _cancelValidatorWhileElect();
  1745  
  1746          uint256 nextEpochValCount = nextEpochValidatorCount();
  1747          uint256 effictiveLen = effictiveValidators.length();
  1748  
  1749          for (uint256 i = 0; i < curEpochValidators.length; i++) {
  1750              address _val = curEpochValidators[i];
  1751              sysRewards.updateValidatorWhileEpochEnd(
  1752                  _val,
  1753                  _validators[_val].votes
  1754              );
  1755              delete curEpochValidatorsIdMap[_val];
  1756          }
  1757          delete curEpochValidators;
  1758  
  1759          uint256 total = 0;
  1760          for (uint256 i = 0; i < effictiveLen; i++) {
  1761              address val = effictiveValidators.at(i);
  1762              total += _validators[val].votes + _validators[val].deposit;
  1763          }
  1764  
  1765          uint256 totalTemp = total;
  1766          uint256 nextEpoch = currentEpoch() + 1;
  1767  
  1768          if (nextEpochValCount >= effictiveLen) {
  1769              for (uint256 i = 0; i < effictiveLen; i++) {
  1770                  address val = effictiveValidators.at(i);
  1771                  curEpochValidators.push(val);
  1772                  curEpochValidatorsIdMap[val] = curEpochValidators.length;
  1773                  sysRewards.updateValidatorWhileElect(
  1774                      val,
  1775                      _validators[val].rate,
  1776                      nextEpoch
  1777                  );
  1778              }
  1779          } else {
  1780              // for-loop tryElect
  1781              for (uint256 i = 0; i < nextEpochValCount; i++) {
  1782                  if (total <= 0) break;
  1783                  // get random number
  1784                  uint256 randDeposit = rand(total, i);
  1785  
  1786                  for (uint256 j = 0; j < effictiveLen; j++) {
  1787                      address val = effictiveValidators.at(j);
  1788                      if (curEpochValidatorsIdMap[val] != 0) continue;
  1789                      uint256 deposit = _validators[val].votes +
  1790                          _validators[val].deposit;
  1791                      if (randDeposit <= deposit) {
  1792                          curEpochValidators.push(val);
  1793                          curEpochValidatorsIdMap[val] = curEpochValidators
  1794                              .length;
  1795                          total -= deposit;
  1796                          sysRewards.updateValidatorWhileElect(
  1797                              val,
  1798                              _validators[val].rate,
  1799                              nextEpoch
  1800                          );
  1801                          break;
  1802                      }
  1803                      randDeposit -= deposit;
  1804                  }
  1805              }
  1806          }
  1807  
  1808          sysRewards.updateEpochWhileElect(
  1809              totalTemp,
  1810              curEpochValidators.length,
  1811              effictiveLen,
  1812              nextEpoch
  1813          );
  1814      }
  1815  
  1816      function rand(uint256 _length, uint256 _i) internal view returns (uint256) {
  1817          uint256 random = uint256(
  1818              keccak256(abi.encodePacked(blockhash(block.number - _i - 1), _i))
  1819          );
  1820          return random % _length;
  1821      }
  1822  
  1823      function recentFourteenEpochAvgValCount() internal view returns (uint256) {
  1824          uint256 curEpoch = currentEpoch();
  1825          if (curEpoch == 0) {
  1826              return effictiveValidators.length();
  1827          }
  1828          uint256 sumValidatorCount = 0;
  1829          uint256 avg = 14;
  1830          if (curEpoch < avg - 1) {
  1831              avg = curEpoch;
  1832          }
  1833          for (uint256 i = 0; i < avg; i++) {
  1834              (, , , uint256 effValCount) = sysRewards.epochs(curEpoch - i);
  1835              sumValidatorCount += effValCount;
  1836          }
  1837          return sumValidatorCount / avg;
  1838      }
  1839  
  1840      function nextEpochValidatorCount() internal view returns (uint256) {
  1841          uint256 avgCount = recentFourteenEpochAvgValCount();
  1842          if (avgCount < MIN_LEVEL_VALIDATOR_COUNT) {
  1843              return MAX_VALIDATOR_COUNT_LV1;
  1844          }
  1845          if (avgCount < MEDIUM_LEVEL_VALIDATOR_COUNT) {
  1846              return MAX_VALIDATOR_COUNT_LV2;
  1847          }
  1848          if (avgCount < MAX_LEVEL_VALIDATOR_COUNT) {
  1849              return MAX_VALIDATOR_COUNT_LV3;
  1850          }
  1851          // avgCount >= MAX_LEVEL_VALIDATOR_COUNT
  1852          return MAX_VALIDATOR_COUNT_LV4;
  1853      }
  1854  
  1855  }
  1856  
  1857  interface IValidators {
  1858      function isEffictiveValidator(address addr) external view returns (bool);
  1859  
  1860      function getEffictiveValidators() external view returns (address[] memory);
  1861  
  1862      function getInvalidValidators() external view returns (address[] memory);
  1863  
  1864      function effictiveValsLength() external view returns (uint256);
  1865  
  1866      function invalidValsLength() external view returns (uint256);
  1867  
  1868      function validators(address _val)
  1869          external
  1870          view
  1871          returns (Validators.Validator calldata);
  1872  
  1873      function kickoutValidator(address _val) external;
  1874  
  1875      function tryElect() external;
  1876  
  1877      function addValidatorFromProposal(
  1878          address _addr,
  1879          uint256 _deposit,
  1880          uint8 _rate,
  1881          string memory _name,
  1882          string memory _details
  1883      ) external payable;
  1884  
  1885      function voteValidator(
  1886          address _voter,
  1887          address _val,
  1888          uint256 _votes
  1889      ) external payable;
  1890  
  1891      function cancelVoteValidator(
  1892          address _voter,
  1893          address _val,
  1894          uint256 _votes,
  1895          bool _clear
  1896      ) external payable;
  1897  
  1898  }
  1899  
  1900  contract SystemRewards is Base, Initializable, ReentrancyGuard {
  1901      using EnumerableSet for EnumerableSet.UintSet;
  1902      using EnumerableSet for EnumerableSet.AddressSet;
  1903  
  1904      struct Reward {
  1905          uint256 validatorReward;
  1906          uint256 delegatorsReward;
  1907          uint8 rate;
  1908      }
  1909  
  1910      struct SysRewards {
  1911          /// @notice pending epochs with block reward
  1912          EnumerableSet.UintSet epochs;
  1913          /// @notice epoch => Reward
  1914          mapping(uint256 => Reward) rewards;
  1915          /// @notice penging validator reward . non real-time
  1916          uint256 pendingReward;
  1917          /// @notice reward per vote for delegates
  1918          uint256 rewardPerVote;
  1919      }
  1920  
  1921      struct SysRewardsInfo {
  1922          uint256[] epochs;
  1923          uint256[] validatorRewards;
  1924          uint256[] delegatorsRewards;
  1925          uint8[] rates;
  1926          uint256 pendingReward;
  1927          uint256 frozenReward;
  1928          uint256 rewardPerVote;
  1929      }
  1930  
  1931      mapping(address => SysRewards) sysRewards;
  1932  
  1933      struct Epoch {
  1934          uint256 blockReward;
  1935          uint256 tvl;
  1936          uint256 validatorCount;
  1937          uint256 effictiveValCount;
  1938          address[] kickoutValidators;
  1939      }
  1940  
  1941      /// @notice epoch => Epoch
  1942      mapping(uint256 => Epoch) public epochs;
  1943  
  1944      IValidators public validatorC;
  1945  
  1946      INodeVote public nodeVoteC;
  1947  
  1948      struct Punish {
  1949          uint256 count;
  1950          uint256[] punishBlocks;
  1951          uint256[] kickoutBlocks;
  1952          uint256[] burnRewards;
  1953      }
  1954  
  1955      /// @notice validator => epoch => Punish
  1956      mapping(address => mapping(uint256 => Punish)) _punishInfo;
  1957  
  1958      /// @notice  validator => block => [_valReward, _delegatorReward]
  1959      mapping(address => mapping(uint256 => uint256[])) _distributeBlockRewardLog;
  1960  
  1961      event LogEarnValidatorReward(address indexed _val, uint256 _amount);
  1962  
  1963      modifier onlyValidatorC() {
  1964          require(
  1965              msg.sender == address(validatorC),
  1966              "SystemRewards: not Validator contract"
  1967          );
  1968          _;
  1969      }
  1970  
  1971      function initialize(address _validator, address _node)
  1972          public
  1973          onlySystem
  1974          initializer
  1975      {
  1976          validatorC = IValidators(_validator);
  1977          nodeVoteC = INodeVote(_node);
  1978      }
  1979  
  1980      function kickoutInfo(uint256 _epoch)
  1981          public
  1982          view
  1983          returns (address[] memory)
  1984      {
  1985          return epochs[_epoch].kickoutValidators;
  1986      }
  1987  
  1988      function punishInfo(address _val, uint256 _epoch)
  1989          public
  1990          view
  1991          returns (Punish memory)
  1992      {
  1993          return _punishInfo[_val][_epoch];
  1994      }
  1995  
  1996      function distributeBlockRewardInfo(address _val, uint256 _block)
  1997          public
  1998          view
  1999          returns (uint256[] memory)
  2000      {
  2001          return _distributeBlockRewardLog[_val][_block];
  2002      }
  2003  
  2004      /**
  2005       * @dev return rewardPerVote of validator
  2006       */
  2007      function getRewardPerVote(address _val) public view returns (uint256) {
  2008          return sysRewards[_val].rewardPerVote;
  2009      }
  2010  
  2011      function validatorEpochRewardInfo(address _val, uint256 _epoch)
  2012          public
  2013          view
  2014          returns (Reward memory)
  2015      {
  2016          return sysRewards[_val].rewards[_epoch];
  2017      }
  2018  
  2019      function validatorRewardsInfo(address _val)
  2020          public
  2021          view
  2022          returns (SysRewardsInfo memory)
  2023      {
  2024          SysRewards storage sysReward = sysRewards[_val];
  2025          (uint256 len, uint256 curEpoch) = (
  2026              sysReward.epochs.length(),
  2027              currentEpoch()
  2028          );
  2029          (uint256 avaliable, uint256 frozen) = (sysReward.pendingReward, 0);
  2030  
  2031          uint256[] memory _epochs = new uint256[](len);
  2032          uint256[] memory validatorRewards = new uint256[](len);
  2033          uint256[] memory delegatorsRewards = new uint256[](len);
  2034          uint8[] memory rates = new uint8[](len);
  2035  
  2036          for (uint256 i = 0; i < len; i++) {
  2037              uint256 epoch = sysReward.epochs.at(i);
  2038              _epochs[i] = epoch;
  2039              validatorRewards[i] = sysReward.rewards[epoch].validatorReward;
  2040              delegatorsRewards[i] = sysReward.rewards[epoch].delegatorsReward;
  2041              rates[i] = sysReward.rewards[epoch].rate;
  2042              if (epoch + VALIDATOR_REWARD_LOCK_EPOCHS < curEpoch) {
  2043                  avaliable += sysReward.rewards[epoch].validatorReward;
  2044              } else {
  2045                  frozen += sysReward.rewards[epoch].validatorReward;
  2046              }
  2047          }
  2048          SysRewardsInfo memory info;
  2049          info.epochs = _epochs;
  2050          info.validatorRewards = validatorRewards;
  2051          info.delegatorsRewards = delegatorsRewards;
  2052          info.rates = rates;
  2053          info.pendingReward = avaliable;
  2054          info.frozenReward = frozen;
  2055          info.rewardPerVote = sysReward.rewardPerVote;
  2056  
  2057          return info;
  2058      }
  2059  
  2060      function pendingValidatorReward(address _val)
  2061          public
  2062          view
  2063          returns (uint256, uint256)
  2064      {
  2065          SysRewards storage sysReward = sysRewards[_val];
  2066          (uint256 len, uint256 curEpoch) = (
  2067              sysReward.epochs.length(),
  2068              currentEpoch()
  2069          );
  2070  
  2071          (uint256 avaliable, uint256 frozen) = (sysReward.pendingReward, 0);
  2072  
  2073          for (uint256 i = 0; i < len; i++) {
  2074              uint256 epoch = sysReward.epochs.at(i);
  2075              if (epoch + VALIDATOR_REWARD_LOCK_EPOCHS < curEpoch) {
  2076                  avaliable += sysReward.rewards[epoch].validatorReward;
  2077              } else {
  2078                  frozen += sysReward.rewards[epoch].validatorReward;
  2079              }
  2080          }
  2081          return (avaliable, frozen);
  2082      }
  2083  
  2084      /**
  2085       * @dev earn validator reward
  2086       */
  2087      function earnValidatorReward() external nonReentrant {
  2088          SysRewards storage sysReward = sysRewards[msg.sender];
  2089          uint256 pendingReward = _updateValidatorPendingReward(
  2090              msg.sender,
  2091              false
  2092          );
  2093          payable(msg.sender).transfer(pendingReward);
  2094          sysReward.pendingReward = 0;
  2095          emit LogEarnValidatorReward(msg.sender, pendingReward);
  2096      }
  2097  
  2098      /**
  2099       * @dev earn validator reward from Validator contract
  2100       */
  2101      function earnValRewardFromValidatorC(address _val) external onlyValidatorC {
  2102          SysRewards storage sysReward = sysRewards[_val];
  2103          uint256 pendingReward = _updateValidatorPendingReward(_val, false);
  2104          if (pendingReward == 0) {
  2105              emit LogEarnValidatorReward(_val, pendingReward);
  2106              return;
  2107          }
  2108          payable(_val).transfer(pendingReward);
  2109          sysReward.pendingReward = 0;
  2110          emit LogEarnValidatorReward(_val, pendingReward);
  2111      }
  2112  
  2113      function distributeBlockReward(uint256 _reward)
  2114          external
  2115          payable
  2116          onlyMiner
  2117          onlySystem
  2118          nonReentrant
  2119      {
  2120          SysRewards storage sysReward = sysRewards[msg.sender];
  2121          uint256 curEpoch = currentEpoch();
  2122  
  2123          uint8 rate = sysReward.rewards[curEpoch].rate;
  2124  
  2125          // calculate block reward
  2126          uint256 delegatorsReward = (_reward * uint256(rate)) /
  2127              uint256(MAX_RATE);
  2128          uint256 valReward = _reward - delegatorsReward;
  2129  
  2130          // distribute block reward
  2131          sysReward.rewards[curEpoch].validatorReward += valReward;
  2132          sysReward.rewards[curEpoch].delegatorsReward += delegatorsReward;
  2133  
  2134          _distributeBlockRewardLog[msg.sender][block.number].push(valReward);
  2135          _distributeBlockRewardLog[msg.sender][block.number].push(
  2136              delegatorsReward
  2137          );
  2138  
  2139          // The previous block when the epoch is updated
  2140          if (block.number % EPOCH_BLOCKS == EPOCH_BLOCKS - 1) {
  2141              // tryElect
  2142              validatorC.tryElect();
  2143          }
  2144      }
  2145  
  2146      function punish(address _val) external onlyMiner onlySystem returns (bool) {
  2147          SysRewards storage sysReward = sysRewards[_val];
  2148          uint256 curEpoch = currentEpoch();
  2149          Punish storage _punish = _punishInfo[_val][curEpoch];
  2150  
  2151          _punish.count += 1;
  2152          _punish.punishBlocks.push(block.number);
  2153  
  2154          if (
  2155              _punish.count >= MAX_PUNISH_COUNT &&
  2156              _punish.count % MAX_PUNISH_COUNT == 0
  2157          ) {
  2158              uint256 curEpochValReward = sysReward
  2159                  .rewards[curEpoch]
  2160                  .validatorReward;
  2161              sysReward.rewards[curEpoch].validatorReward = 0;
  2162              _punish.kickoutBlocks.push(block.number);
  2163              _punish.burnRewards.push(curEpochValReward);
  2164              payable(BLACK_HOLE_ADDRESS).transfer(curEpochValReward);
  2165  
  2166              bool hasKickout = isValidatorKickout(
  2167                  epochs[curEpoch].kickoutValidators,
  2168                  _val
  2169              );
  2170              if (!hasKickout) {
  2171                  epochs[curEpoch].kickoutValidators.push(_val);
  2172                  validatorC.kickoutValidator(_val);
  2173              }
  2174  
  2175              return true;
  2176          }
  2177          return false;
  2178      }
  2179  
  2180      /**
  2181       * @dev update reward epochs and rate while tryElect
  2182       */
  2183      function updateValidatorWhileElect(
  2184          address _val,
  2185          uint8 _rate,
  2186          uint256 _newEpoch
  2187      ) external onlyValidatorC {
  2188          SysRewards storage sysReward = sysRewards[_val];
  2189          sysReward.epochs.add(_newEpoch);
  2190          sysReward.rewards[_newEpoch].rate = _rate;
  2191      }
  2192  
  2193      /**
  2194       * @dev update epoch info while tryElect
  2195       */
  2196      function updateEpochWhileElect(
  2197          uint256 _tvl,
  2198          uint256 _valCount,
  2199          uint256 _effictiveValCount,
  2200          uint256 _newEpoch
  2201      ) external onlyValidatorC {
  2202          epochs[_newEpoch].tvl = _tvl;
  2203          epochs[_newEpoch].validatorCount = _valCount;
  2204          epochs[_newEpoch].effictiveValCount = _effictiveValCount;
  2205          _calculateBlockReward(_newEpoch);
  2206      }
  2207  
  2208      /**
  2209       * @dev update validator rewardPerVote and pendingReward while epoch ending
  2210       */
  2211      function updateValidatorWhileEpochEnd(address _val, uint256 _votes)
  2212          external
  2213          onlyValidatorC
  2214      {
  2215          _updateValidatorPendingReward(_val, true);
  2216  
  2217          SysRewards storage sysReward = sysRewards[_val];
  2218          uint256 curEpoch = currentEpoch();
  2219          if (_votes > 0) {
  2220              sysReward.rewardPerVote +=
  2221                  (sysReward.rewards[curEpoch].delegatorsReward *
  2222                      SAFE_MULTIPLIER) /
  2223                  _votes;
  2224              payable(address(nodeVoteC)).transfer(
  2225                  sysReward.rewards[curEpoch].delegatorsReward
  2226              );
  2227          } else {
  2228              payable(BLACK_HOLE_ADDRESS).transfer(
  2229                  sysReward.rewards[curEpoch].delegatorsReward
  2230              );
  2231          }
  2232      }
  2233  
  2234      /**
  2235       * @dev update validator pendingReward while epoch ending
  2236       */
  2237      function _updateValidatorPendingReward(address _val, bool _isEpochEnd)
  2238          internal
  2239          returns (uint256)
  2240      {
  2241          SysRewards storage sysReward = sysRewards[_val];
  2242          (uint256 len, uint256 curEpoch) = (
  2243              sysReward.epochs.length(),
  2244              currentEpoch()
  2245          );
  2246  
  2247          uint256[] memory _epochs = new uint256[](len);
  2248          for (uint256 i = 0; i < len; i++) {
  2249              _epochs[i] = sysReward.epochs.at(i);
  2250          }
  2251  
  2252          for (uint256 i = 0; i < len; i++) {
  2253              uint256 epoch = _epochs[i];
  2254              if (
  2255                  epoch + VALIDATOR_REWARD_LOCK_EPOCHS < curEpoch ||
  2256                  (_isEpochEnd == true &&
  2257                      epoch + VALIDATOR_REWARD_LOCK_EPOCHS <= curEpoch)
  2258              ) {
  2259                  sysReward.pendingReward += sysReward
  2260                      .rewards[epoch]
  2261                      .validatorReward;
  2262                  sysReward.epochs.remove(epoch);
  2263              }
  2264          }
  2265          return sysReward.pendingReward;
  2266      }
  2267  
  2268      /**
  2269       * @dev calculate epoch's BlockReward while tryElect
  2270       */
  2271      function _calculateBlockReward(uint256 _newEpoch) internal {
  2272          (uint256 sum, uint256 count) = (0, 0);
  2273  
  2274          if (_newEpoch == 0) {
  2275              sum = epochs[_newEpoch].tvl;
  2276              count = 1;
  2277          } else {
  2278              count = _newEpoch >= 14 ? 14 : _newEpoch;
  2279              for (uint256 i = _newEpoch - count; i < _newEpoch; i++) {
  2280                  sum += epochs[i].tvl;
  2281              }
  2282          }
  2283  
  2284          uint256 avg = sum / count;
  2285          if (avg < TOTAL_DEPOSIT_LV1) {
  2286              epochs[_newEpoch].blockReward = REWARD_DEPOSIT_UNDER_LV1;
  2287          } else if (TOTAL_DEPOSIT_LV1 <= avg && avg < TOTAL_DEPOSIT_LV2) {
  2288              epochs[_newEpoch].blockReward = REWARD_DEPOSIT_FROM_LV1_TO_LV2;
  2289          } else if (TOTAL_DEPOSIT_LV2 <= avg && avg < TOTAL_DEPOSIT_LV3) {
  2290              epochs[_newEpoch].blockReward = REWARD_DEPOSIT_FROM_LV2_TO_LV3;
  2291          } else if (TOTAL_DEPOSIT_LV3 <= avg && avg < TOTAL_DEPOSIT_LV4) {
  2292              epochs[_newEpoch].blockReward = REWARD_DEPOSIT_FROM_LV3_TO_LV4;
  2293          } else if (TOTAL_DEPOSIT_LV4 <= avg && avg < TOTAL_DEPOSIT_LV5) {
  2294              epochs[_newEpoch].blockReward = REWARD_DEPOSIT_FROM_LV4_TO_LV5;
  2295          } else {
  2296              epochs[_newEpoch].blockReward = REWARD_DEPOSIT_OVER_LV5;
  2297          }
  2298      }
  2299  
  2300      function isValidatorKickout(address[] memory kkvals, address val)
  2301          internal
  2302          pure
  2303          returns (bool)
  2304      {
  2305          for (uint256 i = 0; i < kkvals.length; i++) {
  2306              if (kkvals[i] == val) {
  2307                  return true;
  2308              }
  2309          }
  2310          return false;
  2311      }
  2312  
  2313  }