github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/consensus/dpos/systemcontract/contracts/NodeVotes.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      function initialize(
  1271          address _proposal,
  1272          address _sysReward,
  1273          address _nodeVote,
  1274          address _initVal,
  1275          uint256 _initDeposit,
  1276          uint8 _initRate,
  1277          string memory _name,
  1278          string memory _details
  1279      ) external payable onlySystem initializer {
  1280          sysRewards = ISystemRewards(_sysReward);
  1281          proposals = IProposals(_proposal);
  1282          nodeVote = INodeVote(_nodeVote);
  1283  
  1284          require(!_initVal.isContract(), "Validators: validator address error");
  1285          require(
  1286              msg.value == _initDeposit && _initDeposit >= MIN_DEPOSIT,
  1287              "Validators: deposit or value error"
  1288          );
  1289          require(
  1290              _initRate >= MIN_RATE && _initRate <= MAX_RATE,
  1291              "Validators: Rate must greater than MIN_RATE and less than MAX_RATE"
  1292          );
  1293  
  1294          Validator storage val = _validators[_initVal];
  1295          val.status = ValidatorStatus.effictive;
  1296          val.deposit = _initDeposit;
  1297          val.rate = _initRate;
  1298          val.name = _name;
  1299          val.details = _details;
  1300  
  1301          effictiveValidators.add(_initVal);
  1302          totalDeposit += _initDeposit;
  1303  
  1304          curEpochValidators.push(_initVal);
  1305          curEpochValidatorsIdMap[_initVal] = curEpochValidators.length;
  1306  
  1307          uint256 curEpoch = currentEpoch();
  1308          sysRewards.updateValidatorWhileElect(_initVal, _initRate, curEpoch);
  1309          sysRewards.updateEpochWhileElect(
  1310              totalDeposit,
  1311              curEpochValidators.length,
  1312              effictiveValidators.length(),
  1313              curEpoch
  1314          );
  1315  
  1316          emit LogAddValidator(_initVal, _initDeposit, _initRate);
  1317      }
  1318  
  1319      /**
  1320       * @dev get voter
  1321       */
  1322      function getValidatorVoters(
  1323          address _val,
  1324          uint256 page,
  1325          uint256 size
  1326      ) external view returns (address[] memory) {
  1327          require(page > 0 && size > 0, "Validators: Requests param error");
  1328          EnumerableSet.AddressSet storage voters = validatorToVoters[_val];
  1329          uint256 start = (page - 1) * size;
  1330          if (voters.length() < start) {
  1331              size = 0;
  1332          } else {
  1333              uint256 length = voters.length() - start;
  1334              if (length < size) {
  1335                  size = length;
  1336              }
  1337          }
  1338  
  1339          address[] memory vals = new address[](size);
  1340          for (uint256 i = 0; i < size; i++) {
  1341              vals[i] = voters.at(i + start);
  1342          }
  1343          return vals;
  1344      }
  1345  
  1346      /**
  1347       * @dev return voters count of validator
  1348       */
  1349      function validatorVotersLength(address _val) public view returns (uint256) {
  1350          return validatorToVoters[_val].length();
  1351      }
  1352  
  1353      /**
  1354       * @dev return validator info
  1355       */
  1356      function validators(address _val) external view returns (Validator memory) {
  1357          return _validators[_val];
  1358      }
  1359  
  1360      /**
  1361       * @dev batch query validator info
  1362       */
  1363      function batchValidators(address[] memory _vals)
  1364          external
  1365          view
  1366          returns (Validator[] memory)
  1367      {
  1368          uint256 len = _vals.length;
  1369          Validator[] memory valInfos = new Validator[](len);
  1370  
  1371          for (uint256 i = 0; i < len; i++) {
  1372              valInfos[i] = _validators[_vals[i]];
  1373          }
  1374          return valInfos;
  1375      }
  1376  
  1377      /**
  1378       * @dev return curEpochValidators
  1379       */
  1380      function getCurEpochValidators() external view returns (address[] memory) {
  1381          return curEpochValidators;
  1382      }
  1383  
  1384      /**
  1385       * @dev True: effictive
  1386       */
  1387      function isEffictiveValidator(address addr) external view returns (bool) {
  1388          return _validators[addr].status == ValidatorStatus.effictive;
  1389      }
  1390  
  1391      /**
  1392       * @dev return effictive Validators count
  1393       */
  1394      function effictiveValsLength() public view returns (uint256) {
  1395          return effictiveValidators.length();
  1396      }
  1397  
  1398      /**
  1399       * @dev return all effictive Validators
  1400       */
  1401      function getEffictiveValidators() public view returns (address[] memory) {
  1402          uint256 len = effictiveValidators.length();
  1403          address[] memory vals = new address[](len);
  1404  
  1405          for (uint256 i = 0; i < len; i++) {
  1406              vals[i] = effictiveValidators.at(i);
  1407          }
  1408          return vals;
  1409      }
  1410  
  1411      function getEffictiveValidatorsWithPage(uint256 page, uint256 size)
  1412          public
  1413          view
  1414          returns (address[] memory)
  1415      {
  1416          require(page > 0 && size > 0, "Validators: Requests param error");
  1417          uint256 len = effictiveValidators.length();
  1418          uint256 start = (page - 1) * size;
  1419          if (len < start) {
  1420              size = 0;
  1421          } else {
  1422              uint256 length = len - start;
  1423              if (length < size) {
  1424                  size = length;
  1425              }
  1426          }
  1427  
  1428          address[] memory vals = new address[](size);
  1429          for (uint256 i = 0; i < size; i++) {
  1430              vals[i] = effictiveValidators.at(i + start);
  1431          }
  1432          return vals;
  1433      }
  1434  
  1435      /**
  1436       * @dev return invalid Validators count
  1437       */
  1438      function invalidValsLength() public view returns (uint256) {
  1439          return invalidValidators.length();
  1440      }
  1441  
  1442      /**
  1443       * @dev return all invalid Validators
  1444       */
  1445      function getInvalidValidators() public view returns (address[] memory) {
  1446          uint256 len = invalidValidators.length();
  1447          address[] memory vals = new address[](len);
  1448  
  1449          for (uint256 i = 0; i < len; i++) {
  1450              vals[i] = invalidValidators.at(i);
  1451          }
  1452          return vals;
  1453      }
  1454  
  1455      function getInvalidValidatorsWithPage(uint256 page, uint256 size)
  1456          public
  1457          view
  1458          returns (address[] memory)
  1459      {
  1460          require(page > 0 && size > 0, "Validators: Requests param error");
  1461          uint256 len = invalidValidators.length();
  1462          uint256 start = (page - 1) * size;
  1463          if (len < start) {
  1464              size = 0;
  1465          } else {
  1466              uint256 length = len - start;
  1467              if (length < size) {
  1468                  size = length;
  1469              }
  1470          }
  1471  
  1472          address[] memory vals = new address[](size);
  1473          for (uint256 i = 0; i < size; i++) {
  1474              vals[i] = invalidValidators.at(i + start);
  1475          }
  1476          return vals;
  1477      }
  1478  
  1479      /**
  1480       * @dev return canceling validators count
  1481       */
  1482      function CancelQueueValidatorsLength() public view returns (uint256) {
  1483          return cancelingValidators.length();
  1484      }
  1485  
  1486      /**
  1487       * @dev return Cancel Queue Validators
  1488       */
  1489      function getCancelQueueValidators() public view returns (address[] memory) {
  1490          uint256 len = cancelingValidators.length();
  1491          address[] memory vals = new address[](len);
  1492  
  1493          for (uint256 i = 0; i < len; i++) {
  1494              vals[i] = cancelingValidators.at(i);
  1495          }
  1496          return vals;
  1497      }
  1498  
  1499      /**
  1500       * @dev update validator deposit
  1501       */
  1502      function updateValidatorDeposit(uint256 _deposit)
  1503          external
  1504          payable
  1505          nonReentrant
  1506      {
  1507          Validator storage val = _validators[msg.sender];
  1508          require(
  1509              val.status == ValidatorStatus.effictive,
  1510              "Validators: illegal msg.sender"
  1511          );
  1512          if (_deposit >= val.deposit) {
  1513              require(
  1514                  msg.value >= _deposit - val.deposit,
  1515                  "Validators: illegal deposit"
  1516              );
  1517              uint256 sub = _deposit - val.deposit;
  1518              totalDeposit += sub;
  1519              val.deposit = _deposit;
  1520              payable(msg.sender).transfer(msg.value - sub);
  1521          } else {
  1522              require(_deposit >= MIN_DEPOSIT, "Validators: illegal deposit");
  1523              uint256 sub = val.deposit - _deposit;
  1524              payable(msg.sender).transfer(sub);
  1525              val.deposit = _deposit;
  1526              totalDeposit -= sub;
  1527          }
  1528  
  1529          emit LogUpdateValidatorDeposit(msg.sender, val.deposit);
  1530      }
  1531  
  1532      /**
  1533       * @dev update validator rate
  1534       */
  1535      function updateValidatorRate(uint8 _rate) external nonReentrant {
  1536          Validator storage val = _validators[msg.sender];
  1537          require(
  1538              val.status == ValidatorStatus.effictive,
  1539              "Validators: illegal msg.sender"
  1540          );
  1541          require(
  1542              val.rateSettLockingEndBlock < block.number,
  1543              "Validators: illegal rate set block"
  1544          );
  1545          require(
  1546              _rate >= MIN_RATE && val.rate <= MAX_RATE,
  1547              "Validators: illegal Allocation ratio"
  1548          );
  1549          uint8 preRate = val.rate;
  1550          val.rate = _rate;
  1551          val.rateSettLockingEndBlock =
  1552              block.number +
  1553              RATE_SET_LOCK_EPOCHS *
  1554              EPOCH_BLOCKS;
  1555  
  1556          emit LogUpdateValidatorRate(msg.sender, preRate, _rate);
  1557      }
  1558  
  1559      /**
  1560       * @dev update validator name and details
  1561       */
  1562      function updateValidatorNameDetails(
  1563          string memory _name,
  1564          string memory _details
  1565      ) external nonReentrant {
  1566          Validator storage val = _validators[msg.sender];
  1567          require(
  1568              bytes(_details).length <= MAX_VALIDATOR_DETAIL_LENGTH,
  1569              "Validators: Details is too long"
  1570          );
  1571          require(
  1572              bytes(_name).length <= MAX_VALIDATOR_NAME_LENGTH,
  1573              "Validators: name is too long"
  1574          );
  1575          val.name = _name;
  1576          val.details = _details;
  1577      }
  1578  
  1579      function addValidatorFromProposal(
  1580          address _val,
  1581          uint256 _deposit,
  1582          uint8 _rate,
  1583          string memory _name,
  1584          string memory _details
  1585      ) external payable onlyProposalsC {
  1586          require(!_val.isContract(), "Validators: validator address error");
  1587          require(
  1588              msg.value == _deposit,
  1589              "Validators: deposit not equal msg.value"
  1590          );
  1591  
  1592          Validator storage val = _validators[_val];
  1593          require(
  1594              val.status == ValidatorStatus.canceled,
  1595              "Validators: validator status error"
  1596          );
  1597  
  1598          val.status = ValidatorStatus.effictive;
  1599          val.deposit = _deposit;
  1600          val.rate = _rate;
  1601          val.name = _name;
  1602          val.details = _details;
  1603  
  1604          effictiveValidators.add(_val);
  1605          invalidValidators.remove(_val);
  1606          totalDeposit += _deposit;
  1607  
  1608          emit LogAddValidator(_val, _deposit, _rate);
  1609      }
  1610  
  1611      function kickoutValidator(address _val) external onlySysRewardsC {
  1612          Validator storage val = _validators[_val];
  1613          require(
  1614              val.status == ValidatorStatus.effictive ||
  1615                  val.status == ValidatorStatus.kickout,
  1616              "Validators: validator status error"
  1617          );
  1618          val.status = ValidatorStatus.kickout;
  1619          if (effictiveValidators.contains(_val)) {
  1620              effictiveValidators.remove(_val);
  1621              invalidValidators.add(_val);
  1622              totalDeposit -= val.deposit;
  1623          }
  1624      }
  1625  
  1626      /**
  1627       * @dev restore validator from kickout status
  1628       */
  1629      function restore() external nonReentrant {
  1630          require(
  1631              effictiveValidators.length() < MAX_VALIDATORS_COUNT,
  1632              "Validators: length of the validator must be less than MAX_VALIDATORS_COUNT"
  1633          );
  1634          Validator storage val = _validators[msg.sender];
  1635          require(
  1636              !cancelingValidators.contains(msg.sender),
  1637              "Validators: this validator is canceling"
  1638          );
  1639          require(
  1640              val.status == ValidatorStatus.kickout,
  1641              "Validators: validator must be kickout"
  1642          );
  1643          val.status = ValidatorStatus.effictive;
  1644          effictiveValidators.add(msg.sender);
  1645          invalidValidators.remove(msg.sender);
  1646          totalDeposit += val.deposit;
  1647  
  1648          emit LogRestoreValidator(msg.sender);
  1649      }
  1650  
  1651      function unstake() external nonReentrant {
  1652          Validator storage val = _validators[msg.sender];
  1653          require(
  1654              val.status == ValidatorStatus.effictive ||
  1655                  val.status == ValidatorStatus.kickout,
  1656              "Validators: illegal msg.sender"
  1657          );
  1658          if (curEpochValidatorsIdMap[msg.sender] == 0) {
  1659              cancelingValidators.remove(msg.sender);
  1660              val.status = ValidatorStatus.canceling;
  1661              val.unstakeLockingEndBlock =
  1662                  block.number +
  1663                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1664                  EPOCH_BLOCKS;
  1665  
  1666              if (effictiveValidators.contains(msg.sender)) {
  1667                  effictiveValidators.remove(msg.sender);
  1668                  invalidValidators.add(msg.sender);
  1669                  totalDeposit -= val.deposit;
  1670              }
  1671          } else {
  1672              val.status = ValidatorStatus.cancelQueue;
  1673              cancelingValidators.add(msg.sender);
  1674          }
  1675          emit LogUnstakeValidator(msg.sender);
  1676      }
  1677  
  1678      function _cancelValidatorWhileElect() internal {
  1679          for (uint256 i = 0; i < cancelingValidators.length(); i++) {
  1680              address _val = cancelingValidators.at(0);
  1681  
  1682              Validator storage val = _validators[_val];
  1683              val.status = ValidatorStatus.canceling;
  1684              val.unstakeLockingEndBlock =
  1685                  block.number +
  1686                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1687                  EPOCH_BLOCKS;
  1688  
  1689              cancelingValidators.remove(_val);
  1690  
  1691              if (effictiveValidators.contains(_val)) {
  1692                  effictiveValidators.remove(_val);
  1693                  invalidValidators.add(_val);
  1694                  totalDeposit -= val.deposit;
  1695              }
  1696          }
  1697      }
  1698  
  1699      function redeem() external nonReentrant {
  1700          Validator storage val = _validators[msg.sender];
  1701          require(
  1702              val.unstakeLockingEndBlock < block.number,
  1703              "Validators: illegal redeem block"
  1704          );
  1705          require(
  1706              val.status == ValidatorStatus.canceling &&
  1707                  curEpochValidatorsIdMap[msg.sender] == 0,
  1708              "Validators: illegal msg.sender"
  1709          );
  1710  
  1711          val.status = ValidatorStatus.canceled;
  1712          payable(msg.sender).transfer(val.deposit);
  1713          val.deposit = 0;
  1714          val.unstakeLockingEndBlock = 0;
  1715          val.rateSettLockingEndBlock = 0;
  1716          invalidValidators.remove(msg.sender);
  1717  
  1718          emit LogRedeemValidator(msg.sender);
  1719      }
  1720  
  1721      function voteValidator(
  1722          address _voter,
  1723          address _val,
  1724          uint256 _votes
  1725      ) external payable onlyNodeVoteC {
  1726          _validators[_val].votes += _votes;
  1727          validatorToVoters[_val].add(_voter);
  1728      }
  1729  
  1730      function cancelVoteValidator(
  1731          address _voter,
  1732          address _val,
  1733          uint256 _votes,
  1734          bool _clear
  1735      ) external onlyNodeVoteC {
  1736          _validators[_val].votes -= _votes;
  1737          if (_clear) {
  1738              validatorToVoters[_val].remove(_voter);
  1739          }
  1740      }
  1741  
  1742      function tryElect() external onlySysRewardsC {
  1743          _cancelValidatorWhileElect();
  1744  
  1745          uint256 nextEpochValCount = nextEpochValidatorCount();
  1746          uint256 effictiveLen = effictiveValidators.length();
  1747  
  1748          for (uint256 i = 0; i < curEpochValidators.length; i++) {
  1749              address _val = curEpochValidators[i];
  1750              sysRewards.updateValidatorWhileEpochEnd(
  1751                  _val,
  1752                  _validators[_val].votes
  1753              );
  1754              delete curEpochValidatorsIdMap[_val];
  1755          }
  1756          delete curEpochValidators;
  1757  
  1758          uint256 total = 0;
  1759          for (uint256 i = 0; i < effictiveLen; i++) {
  1760              address val = effictiveValidators.at(i);
  1761              total += _validators[val].votes + _validators[val].deposit;
  1762          }
  1763  
  1764          uint256 totalTemp = total;
  1765          uint256 nextEpoch = currentEpoch() + 1;
  1766  
  1767          if (nextEpochValCount >= effictiveLen) {
  1768              for (uint256 i = 0; i < effictiveLen; i++) {
  1769                  address val = effictiveValidators.at(i);
  1770                  curEpochValidators.push(val);
  1771                  curEpochValidatorsIdMap[val] = curEpochValidators.length;
  1772                  sysRewards.updateValidatorWhileElect(
  1773                      val,
  1774                      _validators[val].rate,
  1775                      nextEpoch
  1776                  );
  1777              }
  1778          } else {
  1779              // for-loop tryElect
  1780              for (uint256 i = 0; i < nextEpochValCount; i++) {
  1781                  if (total <= 0) break;
  1782                  // get random number
  1783                  uint256 randDeposit = rand(total, i);
  1784  
  1785                  for (uint256 j = 0; j < effictiveLen; j++) {
  1786                      address val = effictiveValidators.at(j);
  1787                      if (curEpochValidatorsIdMap[val] != 0) continue;
  1788                      uint256 deposit = _validators[val].votes +
  1789                          _validators[val].deposit;
  1790                      if (randDeposit <= deposit) {
  1791                          curEpochValidators.push(val);
  1792                          curEpochValidatorsIdMap[val] = curEpochValidators
  1793                              .length;
  1794                          total -= deposit;
  1795                          sysRewards.updateValidatorWhileElect(
  1796                              val,
  1797                              _validators[val].rate,
  1798                              nextEpoch
  1799                          );
  1800                          break;
  1801                      }
  1802                      randDeposit -= deposit;
  1803                  }
  1804              }
  1805          }
  1806  
  1807          sysRewards.updateEpochWhileElect(
  1808              totalTemp,
  1809              curEpochValidators.length,
  1810              effictiveLen,
  1811              nextEpoch
  1812          );
  1813      }
  1814  
  1815      function rand(uint256 _length, uint256 _i) internal view returns (uint256) {
  1816          uint256 random = uint256(
  1817              keccak256(abi.encodePacked(blockhash(block.number - _i - 1), _i))
  1818          );
  1819          return random % _length;
  1820      }
  1821  
  1822      function recentFourteenEpochAvgValCount() internal view returns (uint256) {
  1823          uint256 curEpoch = currentEpoch();
  1824          if (curEpoch == 0) {
  1825              return effictiveValidators.length();
  1826          }
  1827          uint256 sumValidatorCount = 0;
  1828          uint256 avg = 14;
  1829          if (curEpoch < avg - 1) {
  1830              avg = curEpoch;
  1831          }
  1832          for (uint256 i = 0; i < avg; i++) {
  1833              (, , , uint256 effValCount) = sysRewards.epochs(curEpoch - i);
  1834              sumValidatorCount += effValCount;
  1835          }
  1836          return sumValidatorCount / avg;
  1837      }
  1838  
  1839      function nextEpochValidatorCount() internal view returns (uint256) {
  1840          uint256 avgCount = recentFourteenEpochAvgValCount();
  1841          if (avgCount < MIN_LEVEL_VALIDATOR_COUNT) {
  1842              return MAX_VALIDATOR_COUNT_LV1;
  1843          }
  1844          if (avgCount < MEDIUM_LEVEL_VALIDATOR_COUNT) {
  1845              return MAX_VALIDATOR_COUNT_LV2;
  1846          }
  1847          if (avgCount < MAX_LEVEL_VALIDATOR_COUNT) {
  1848              return MAX_VALIDATOR_COUNT_LV3;
  1849          }
  1850          // avgCount >= MAX_LEVEL_VALIDATOR_COUNT
  1851          return MAX_VALIDATOR_COUNT_LV4;
  1852      }
  1853  
  1854  }
  1855  
  1856  interface IValidators {
  1857      function isEffictiveValidator(address addr) external view returns (bool);
  1858  
  1859      function getEffictiveValidators() external view returns (address[] memory);
  1860  
  1861      function getInvalidValidators() external view returns (address[] memory);
  1862  
  1863      function effictiveValsLength() external view returns (uint256);
  1864  
  1865      function invalidValsLength() external view returns (uint256);
  1866  
  1867      function validators(address _val)
  1868          external
  1869          view
  1870          returns (Validators.Validator calldata);
  1871  
  1872      function kickoutValidator(address _val) external;
  1873  
  1874      function tryElect() external;
  1875  
  1876      function addValidatorFromProposal(
  1877          address _addr,
  1878          uint256 _deposit,
  1879          uint8 _rate,
  1880          string memory _name,
  1881          string memory _details
  1882      ) external payable;
  1883  
  1884      function voteValidator(
  1885          address _voter,
  1886          address _val,
  1887          uint256 _votes
  1888      ) external payable;
  1889  
  1890      function cancelVoteValidator(
  1891          address _voter,
  1892          address _val,
  1893          uint256 _votes,
  1894          bool _clear
  1895      ) external payable;
  1896  
  1897  }
  1898  
  1899  contract NodeVotes is Base, Initializable, ReentrancyGuard {
  1900      using EnumerableSet for EnumerableSet.AddressSet;
  1901      using EnumerableSet for EnumerableSet.UintSet;
  1902  
  1903      struct VoteInfo {
  1904          uint256 amount;
  1905          uint256 rewardDebt;
  1906      }
  1907  
  1908      struct RedeemInfo {
  1909          EnumerableSet.UintSet epochs;
  1910          mapping(uint256 => uint256) epochRedeemVotes;
  1911      }
  1912  
  1913      struct VotesRewardRedeemInfo {
  1914          address validator;
  1915          string validatorName;
  1916          uint8 validatorRate;
  1917          uint256 validatorTotalVotes;
  1918          uint256 amount;
  1919          uint256 pendingReward;
  1920          uint256 pendingRedeem;
  1921          uint256[] lockRedeemEpochs;
  1922          uint256[] lockRedeemVotes;
  1923      }
  1924  
  1925      mapping(address => EnumerableSet.AddressSet) voterValidators;
  1926      mapping(address => mapping(address => VoteInfo)) public voteInfos;
  1927      mapping(address => mapping(address => RedeemInfo)) redeemInfos;
  1928  
  1929      /// @notice Validators contract
  1930      IValidators public validators;
  1931  
  1932      /// @notice SystemRewards contract
  1933      ISystemRewards public sysRewards;
  1934  
  1935      uint256 public totalVotes;
  1936  
  1937      event LogVote(
  1938          address indexed voter,
  1939          address indexed validator,
  1940          uint256 votes
  1941      );
  1942      event LogCancelVote(
  1943          address indexed voter,
  1944          address indexed validator,
  1945          uint256 votes
  1946      );
  1947      event LogRedeem(
  1948          address indexed voter,
  1949          address indexed validator,
  1950          uint256 votes
  1951      );
  1952      event LogEarn(
  1953          address indexed voter,
  1954          address indexed validator,
  1955          uint256 reward
  1956      );
  1957      event LogRewardTransfer(
  1958          address indexed from,
  1959          address indexed to,
  1960          uint256 amount
  1961      );
  1962  
  1963      receive() external payable {}
  1964  
  1965      /**
  1966       * @dev initialize
  1967       */
  1968      function initialize(address _validator, address _sysReward)
  1969          public
  1970          onlySystem
  1971          initializer
  1972      {
  1973          validators = IValidators(_validator);
  1974          sysRewards = ISystemRewards(_sysReward);
  1975      }
  1976  
  1977      /**
  1978       * @dev pending vote reward
  1979       */
  1980      function pendingReward(address _val, address _voter)
  1981          public
  1982          view
  1983          returns (uint256)
  1984      {
  1985          VoteInfo memory voteInfo = voteInfos[_voter][_val];
  1986          uint256 rewardPerVote = sysRewards.getRewardPerVote(_val);
  1987  
  1988          return
  1989              ((voteInfo.amount * rewardPerVote) / SAFE_MULTIPLIER) -
  1990              voteInfo.rewardDebt;
  1991      }
  1992  
  1993      /**
  1994       * @dev pending redeem votes
  1995       */
  1996      function pendingRedeem(address _val, address _voter)
  1997          public
  1998          view
  1999          returns (uint256)
  2000      {
  2001          RedeemInfo storage redeemInfo = redeemInfos[_voter][_val];
  2002  
  2003          (uint256 sumRedeem, uint256 curEpoch) = (0, currentEpoch());
  2004  
  2005          for (uint256 i = 0; i < redeemInfo.epochs.length(); i++) {
  2006              uint256 redeemEpoch = redeemInfo.epochs.at(i);
  2007              if (curEpoch >= redeemEpoch) {
  2008                  sumRedeem += redeemInfo.epochRedeemVotes[redeemEpoch];
  2009              }
  2010          }
  2011          return sumRedeem;
  2012      }
  2013  
  2014      /**
  2015       * @dev vote validator count
  2016       */
  2017      function voteListLength(address _voter) external view returns (uint256) {
  2018          return voterValidators[_voter].length();
  2019      }
  2020  
  2021      function votesRewardRedeemInfo(address _val, address _voter)
  2022          public
  2023          view
  2024          returns (VotesRewardRedeemInfo memory)
  2025      {
  2026          VotesRewardRedeemInfo memory info;
  2027          info.validator = _val;
  2028  
  2029          Validators.Validator memory valInfo = validators.validators(_val);
  2030          info.validatorName = valInfo.name;
  2031          info.validatorRate = valInfo.rate;
  2032          info.validatorTotalVotes = valInfo.votes;
  2033  
  2034          if (!voterValidators[_voter].contains(_val)) return info;
  2035  
  2036          VoteInfo memory voteInfo = voteInfos[_voter][_val];
  2037  
  2038          info.amount = voteInfo.amount;
  2039          info.pendingReward = pendingReward(_val, _voter);
  2040  
  2041          RedeemInfo storage redeemInfo = redeemInfos[_voter][_val];
  2042          (uint256 sumRedeem, uint256 lockRedeemLen, uint256 curEpoch) = (
  2043              0,
  2044              0,
  2045              currentEpoch()
  2046          );
  2047  
  2048          for (uint256 i = 0; i < redeemInfo.epochs.length(); i++) {
  2049              uint256 redeemEpoch = redeemInfo.epochs.at(i);
  2050              if (curEpoch >= redeemEpoch) {
  2051                  sumRedeem += redeemInfo.epochRedeemVotes[redeemEpoch];
  2052              } else {
  2053                  lockRedeemLen += 1;
  2054              }
  2055          }
  2056          if (sumRedeem > 0) info.pendingRedeem = sumRedeem;
  2057  
  2058          if (lockRedeemLen != 0) {
  2059              uint256[] memory lockRedeemEpochs = new uint256[](lockRedeemLen);
  2060              uint256[] memory lockRedeemVotes = new uint256[](lockRedeemLen);
  2061              for (uint256 i = 0; i < redeemInfo.epochs.length(); i++) {
  2062                  uint256 redeemEpoch = redeemInfo.epochs.at(i);
  2063                  if (curEpoch < redeemEpoch) {
  2064                      lockRedeemEpochs[i] = redeemEpoch;
  2065                      lockRedeemVotes[i] = redeemInfo.epochRedeemVotes[
  2066                          redeemEpoch
  2067                      ];
  2068                  }
  2069              }
  2070              info.lockRedeemEpochs = lockRedeemEpochs;
  2071              info.lockRedeemVotes = lockRedeemVotes;
  2072          }
  2073          return info;
  2074      }
  2075  
  2076      /**
  2077       * @dev all votesRewardRedeemInfo with page
  2078       */
  2079      function votesRewardRedeemInfoWithPage(
  2080          address _voter,
  2081          uint256 page,
  2082          uint256 size
  2083      ) external view returns (VotesRewardRedeemInfo[] memory) {
  2084          require(page > 0 && size > 0, "NodeVotes: Requests param error");
  2085  
  2086          uint256 start = (page - 1) * size;
  2087          if (voterValidators[_voter].length() < start) {
  2088              size = 0;
  2089          } else {
  2090              uint256 length = voterValidators[_voter].length() - start;
  2091              if (length < size) {
  2092                  size = length;
  2093              }
  2094          }
  2095  
  2096          VotesRewardRedeemInfo[] memory infos = new VotesRewardRedeemInfo[](
  2097              size
  2098          );
  2099          for (uint256 i = 0; i < size; i++) {
  2100              infos[i] = votesRewardRedeemInfo(
  2101                  voterValidators[_voter].at(i + start),
  2102                  _voter
  2103              );
  2104          }
  2105          return infos;
  2106      }
  2107  
  2108      function earn(address _val) public nonReentrant {
  2109          VoteInfo storage voteInfo = voteInfos[msg.sender][_val];
  2110  
  2111          uint256 rewardPerVote = sysRewards.getRewardPerVote(_val);
  2112          uint256 pending = ((voteInfo.amount * rewardPerVote) /
  2113              SAFE_MULTIPLIER) - voteInfo.rewardDebt;
  2114  
  2115          if (pending == 0) {
  2116              emit LogEarn(msg.sender, _val, pending);
  2117              return;
  2118          }
  2119  
  2120          _safeRewardTransfer(pending);
  2121  
  2122          voteInfo.rewardDebt =
  2123              (voteInfo.amount * rewardPerVote) /
  2124              SAFE_MULTIPLIER;
  2125          emit LogEarn(msg.sender, _val, pending);
  2126      }
  2127  
  2128      function vote(address _val) external payable nonReentrant {
  2129          require(
  2130              !Address.isContract(msg.sender),
  2131              "NodeVotes: The msg.sender can not be contract address"
  2132          );
  2133          require(
  2134              validators.isEffictiveValidator(_val),
  2135              "NodeVotes: The val must be validator"
  2136          );
  2137          require(
  2138              msg.value >= 1 ether,
  2139              "NodeVotes: Vote must greater than 1 ether"
  2140          );
  2141  
  2142          VoteInfo storage voteInfo = voteInfos[msg.sender][_val];
  2143          voterValidators[msg.sender].add(_val);
  2144  
  2145          uint256 rewardPerVote = sysRewards.getRewardPerVote(_val);
  2146  
  2147          if (voteInfo.amount > 0) {
  2148              uint256 pending = ((voteInfo.amount * rewardPerVote) /
  2149                  SAFE_MULTIPLIER) - voteInfo.rewardDebt;
  2150              if (pending > 0) {
  2151                  _safeRewardTransfer(pending);
  2152                  emit LogEarn(msg.sender, _val, pending);
  2153              }
  2154          }
  2155  
  2156          voteInfo.amount += msg.value;
  2157          voteInfo.rewardDebt =
  2158              (voteInfo.amount * rewardPerVote) /
  2159              SAFE_MULTIPLIER;
  2160          totalVotes += msg.value;
  2161          validators.voteValidator(msg.sender, _val, msg.value);
  2162  
  2163          emit LogVote(msg.sender, _val, msg.value);
  2164      }
  2165  
  2166      /**
  2167       * @dev redeem votes
  2168       */
  2169      function redeem(address _val) external nonReentrant {
  2170          require(
  2171              !Address.isContract(msg.sender),
  2172              "NodeVotes: The msg.sender can not be contract address"
  2173          );
  2174          _redeem(_val);
  2175      }
  2176  
  2177      function _redeem(address _val) internal {
  2178          RedeemInfo storage redeemInfo = redeemInfos[msg.sender][_val];
  2179  
  2180          (uint256 sumRedeem, uint256 curEpoch) = (0, currentEpoch());
  2181  
  2182          for (uint256 i = 0; i < redeemInfo.epochs.length(); i++) {
  2183              uint256 redeemEpoch = redeemInfo.epochs.at(0);
  2184              if (curEpoch >= redeemEpoch) {
  2185                  redeemInfo.epochs.remove(redeemEpoch);
  2186                  sumRedeem += redeemInfo.epochRedeemVotes[redeemEpoch];
  2187              }
  2188          }
  2189          if (sumRedeem > 0) {
  2190              payable(msg.sender).transfer(sumRedeem);
  2191              emit LogRedeem(msg.sender, _val, sumRedeem);
  2192          }
  2193  
  2194          VoteInfo storage voteInfo = voteInfos[msg.sender][_val];
  2195          if (voteInfo.amount == 0 && redeemInfo.epochs.length() == 0) {
  2196              voterValidators[msg.sender].remove(_val);
  2197          }
  2198      }
  2199  
  2200      function cancelVote(address _val, uint256 _amount) external nonReentrant {
  2201          require(
  2202              !Address.isContract(msg.sender),
  2203              "NodeVotes: The msg.sender can not be contract address"
  2204          );
  2205  
  2206          VoteInfo storage voteInfo = voteInfos[msg.sender][_val];
  2207          require(
  2208              voterValidators[msg.sender].contains(_val),
  2209              "NodeVotes: The msg.sender did not vote this validator"
  2210          );
  2211          require(
  2212              _amount > 0 && voteInfo.amount >= _amount,
  2213              "NodeVotes: cancel vote amount error"
  2214          );
  2215  
  2216          RedeemInfo storage redeemInfo = redeemInfos[msg.sender][_val];
  2217  
  2218          uint256 rewardPerVote = sysRewards.getRewardPerVote(_val);
  2219          uint256 pending = ((voteInfo.amount * rewardPerVote) /
  2220              SAFE_MULTIPLIER) - voteInfo.rewardDebt;
  2221          if (pending > 0) {
  2222              _safeRewardTransfer(pending);
  2223              emit LogEarn(msg.sender, _val, pending);
  2224          }
  2225  
  2226          _redeem(_val);
  2227  
  2228          totalVotes -= _amount;
  2229          voteInfo.amount -= _amount;
  2230          voteInfo.rewardDebt =
  2231              (voteInfo.amount * rewardPerVote) /
  2232              SAFE_MULTIPLIER;
  2233  
  2234          uint256 curEpoch = currentEpoch();
  2235          uint256 redeemEpoch = curEpoch + VOTE_CANCEL_EPOCHS;
  2236          redeemInfo.epochs.add(redeemEpoch);
  2237          redeemInfo.epochRedeemVotes[redeemEpoch] += _amount;
  2238  
  2239          validators.cancelVoteValidator(
  2240              msg.sender,
  2241              _val,
  2242              _amount,
  2243              voteInfo.amount == 0
  2244          );
  2245  
  2246          emit LogCancelVote(msg.sender, _val, _amount);
  2247      }
  2248  
  2249      function _safeRewardTransfer(uint256 _reward) internal {
  2250          uint256 availableReward = address(this).balance;
  2251          if (_reward > availableReward) {
  2252              payable(msg.sender).transfer(availableReward);
  2253              emit LogRewardTransfer(address(this), msg.sender, availableReward);
  2254          } else {
  2255              payable(msg.sender).transfer(_reward);
  2256              emit LogRewardTransfer(address(this), msg.sender, _reward);
  2257          }
  2258      }
  2259  
  2260  }