github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/consensus/dpos/systemcontract/contracts/Proposals.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      function restore() external nonReentrant {
  1628          require(
  1629              effictiveValidators.length() < MAX_VALIDATORS_COUNT,
  1630              "Validators: length of the validator must be less than MAX_VALIDATORS_COUNT"
  1631          );
  1632          Validator storage val = _validators[msg.sender];
  1633          require(
  1634              !cancelingValidators.contains(msg.sender),
  1635              "Validators: this validator is canceling"
  1636          );
  1637          require(
  1638              val.status == ValidatorStatus.kickout,
  1639              "Validators: validator must be kickout"
  1640          );
  1641          val.status = ValidatorStatus.effictive;
  1642          effictiveValidators.add(msg.sender);
  1643          invalidValidators.remove(msg.sender);
  1644          totalDeposit += val.deposit;
  1645  
  1646          emit LogRestoreValidator(msg.sender);
  1647      }
  1648  
  1649      function unstake() external nonReentrant {
  1650          Validator storage val = _validators[msg.sender];
  1651          require(
  1652              val.status == ValidatorStatus.effictive ||
  1653                  val.status == ValidatorStatus.kickout,
  1654              "Validators: illegal msg.sender"
  1655          );
  1656          if (curEpochValidatorsIdMap[msg.sender] == 0) {
  1657              cancelingValidators.remove(msg.sender);
  1658              val.status = ValidatorStatus.canceling;
  1659              val.unstakeLockingEndBlock =
  1660                  block.number +
  1661                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1662                  EPOCH_BLOCKS;
  1663  
  1664              if (effictiveValidators.contains(msg.sender)) {
  1665                  effictiveValidators.remove(msg.sender);
  1666                  invalidValidators.add(msg.sender);
  1667                  totalDeposit -= val.deposit;
  1668              }
  1669          } else {
  1670              val.status = ValidatorStatus.cancelQueue;
  1671              cancelingValidators.add(msg.sender);
  1672          }
  1673          emit LogUnstakeValidator(msg.sender);
  1674      }
  1675  
  1676      function _cancelValidatorWhileElect() internal {
  1677          for (uint256 i = 0; i < cancelingValidators.length(); i++) {
  1678              address _val = cancelingValidators.at(0);
  1679  
  1680              Validator storage val = _validators[_val];
  1681              val.status = ValidatorStatus.canceling;
  1682              val.unstakeLockingEndBlock =
  1683                  block.number +
  1684                  VALIDATOR_UNSTAKE_LOCK_EPOCHS *
  1685                  EPOCH_BLOCKS;
  1686  
  1687              cancelingValidators.remove(_val);
  1688  
  1689              if (effictiveValidators.contains(_val)) {
  1690                  effictiveValidators.remove(_val);
  1691                  invalidValidators.add(_val);
  1692                  totalDeposit -= val.deposit;
  1693              }
  1694          }
  1695      }
  1696  
  1697      function redeem() external nonReentrant {
  1698          Validator storage val = _validators[msg.sender];
  1699          require(
  1700              val.unstakeLockingEndBlock < block.number,
  1701              "Validators: illegal redeem block"
  1702          );
  1703          require(
  1704              val.status == ValidatorStatus.canceling &&
  1705                  curEpochValidatorsIdMap[msg.sender] == 0,
  1706              "Validators: illegal msg.sender"
  1707          );
  1708  
  1709          val.status = ValidatorStatus.canceled;
  1710          payable(msg.sender).transfer(val.deposit);
  1711          val.deposit = 0;
  1712          val.unstakeLockingEndBlock = 0;
  1713          val.rateSettLockingEndBlock = 0;
  1714          invalidValidators.remove(msg.sender);
  1715  
  1716          emit LogRedeemValidator(msg.sender);
  1717      }
  1718  
  1719      function voteValidator(
  1720          address _voter,
  1721          address _val,
  1722          uint256 _votes
  1723      ) external payable onlyNodeVoteC {
  1724          _validators[_val].votes += _votes;
  1725          validatorToVoters[_val].add(_voter);
  1726      }
  1727  
  1728      function cancelVoteValidator(
  1729          address _voter,
  1730          address _val,
  1731          uint256 _votes,
  1732          bool _clear
  1733      ) external onlyNodeVoteC {
  1734          _validators[_val].votes -= _votes;
  1735          if (_clear) {
  1736              validatorToVoters[_val].remove(_voter);
  1737          }
  1738      }
  1739  
  1740      function tryElect() external onlySysRewardsC {
  1741          _cancelValidatorWhileElect();
  1742  
  1743          uint256 nextEpochValCount = nextEpochValidatorCount();
  1744          uint256 effictiveLen = effictiveValidators.length();
  1745  
  1746          for (uint256 i = 0; i < curEpochValidators.length; i++) {
  1747              address _val = curEpochValidators[i];
  1748              sysRewards.updateValidatorWhileEpochEnd(
  1749                  _val,
  1750                  _validators[_val].votes
  1751              );
  1752              delete curEpochValidatorsIdMap[_val];
  1753          }
  1754          delete curEpochValidators;
  1755  
  1756          uint256 total = 0;
  1757          for (uint256 i = 0; i < effictiveLen; i++) {
  1758              address val = effictiveValidators.at(i);
  1759              total += _validators[val].votes + _validators[val].deposit;
  1760          }
  1761  
  1762          uint256 totalTemp = total;
  1763          uint256 nextEpoch = currentEpoch() + 1;
  1764  
  1765          if (nextEpochValCount >= effictiveLen) {
  1766              for (uint256 i = 0; i < effictiveLen; i++) {
  1767                  address val = effictiveValidators.at(i);
  1768                  curEpochValidators.push(val);
  1769                  curEpochValidatorsIdMap[val] = curEpochValidators.length;
  1770                  sysRewards.updateValidatorWhileElect(
  1771                      val,
  1772                      _validators[val].rate,
  1773                      nextEpoch
  1774                  );
  1775              }
  1776          } else {
  1777              // for-loop tryElect
  1778              for (uint256 i = 0; i < nextEpochValCount; i++) {
  1779                  if (total <= 0) break;
  1780                  // get random number
  1781                  uint256 randDeposit = rand(total, i);
  1782  
  1783                  for (uint256 j = 0; j < effictiveLen; j++) {
  1784                      address val = effictiveValidators.at(j);
  1785                      if (curEpochValidatorsIdMap[val] != 0) continue;
  1786                      uint256 deposit = _validators[val].votes +
  1787                          _validators[val].deposit;
  1788                      if (randDeposit <= deposit) {
  1789                          curEpochValidators.push(val);
  1790                          curEpochValidatorsIdMap[val] = curEpochValidators
  1791                              .length;
  1792                          total -= deposit;
  1793                          sysRewards.updateValidatorWhileElect(
  1794                              val,
  1795                              _validators[val].rate,
  1796                              nextEpoch
  1797                          );
  1798                          break;
  1799                      }
  1800                      randDeposit -= deposit;
  1801                  }
  1802              }
  1803          }
  1804  
  1805          sysRewards.updateEpochWhileElect(
  1806              totalTemp,
  1807              curEpochValidators.length,
  1808              effictiveLen,
  1809              nextEpoch
  1810          );
  1811      }
  1812  
  1813      function rand(uint256 _length, uint256 _i) internal view returns (uint256) {
  1814          uint256 random = uint256(
  1815              keccak256(abi.encodePacked(blockhash(block.number - _i - 1), _i))
  1816          );
  1817          return random % _length;
  1818      }
  1819  
  1820      function recentFourteenEpochAvgValCount() internal view returns (uint256) {
  1821          uint256 curEpoch = currentEpoch();
  1822          if (curEpoch == 0) {
  1823              return effictiveValidators.length();
  1824          }
  1825          uint256 sumValidatorCount = 0;
  1826          uint256 avg = 14;
  1827          if (curEpoch < avg - 1) {
  1828              avg = curEpoch;
  1829          }
  1830          for (uint256 i = 0; i < avg; i++) {
  1831              (, , , uint256 effValCount) = sysRewards.epochs(curEpoch - i);
  1832              sumValidatorCount += effValCount;
  1833          }
  1834          return sumValidatorCount / avg;
  1835      }
  1836  
  1837      function nextEpochValidatorCount() internal view returns (uint256) {
  1838          uint256 avgCount = recentFourteenEpochAvgValCount();
  1839          if (avgCount < MIN_LEVEL_VALIDATOR_COUNT) {
  1840              return MAX_VALIDATOR_COUNT_LV1;
  1841          }
  1842          if (avgCount < MEDIUM_LEVEL_VALIDATOR_COUNT) {
  1843              return MAX_VALIDATOR_COUNT_LV2;
  1844          }
  1845          if (avgCount < MAX_LEVEL_VALIDATOR_COUNT) {
  1846              return MAX_VALIDATOR_COUNT_LV3;
  1847          }
  1848          // avgCount >= MAX_LEVEL_VALIDATOR_COUNT
  1849          return MAX_VALIDATOR_COUNT_LV4;
  1850      }
  1851  
  1852  }
  1853  
  1854  interface IValidators {
  1855      function isEffictiveValidator(address addr) external view returns (bool);
  1856  
  1857      function getEffictiveValidators() external view returns (address[] memory);
  1858  
  1859      function getInvalidValidators() external view returns (address[] memory);
  1860  
  1861      function effictiveValsLength() external view returns (uint256);
  1862  
  1863      function invalidValsLength() external view returns (uint256);
  1864  
  1865      function validators(address _val)
  1866          external
  1867          view
  1868          returns (Validators.Validator calldata);
  1869  
  1870      function kickoutValidator(address _val) external;
  1871  
  1872      function tryElect() external;
  1873  
  1874      function addValidatorFromProposal(
  1875          address _addr,
  1876          uint256 _deposit,
  1877          uint8 _rate,
  1878          string memory _name,
  1879          string memory _details
  1880      ) external payable;
  1881  
  1882      function voteValidator(
  1883          address _voter,
  1884          address _val,
  1885          uint256 _votes
  1886      ) external payable;
  1887  
  1888      function cancelVoteValidator(
  1889          address _voter,
  1890          address _val,
  1891          uint256 _votes,
  1892          bool _clear
  1893      ) external payable;
  1894  
  1895  }
  1896  
  1897  contract Proposals is Base, Initializable, ReentrancyGuard {
  1898      using EnumerableSet for EnumerableSet.Bytes32Set;
  1899  
  1900      enum ProposalType {
  1901          init
  1902      }
  1903  
  1904      enum ProposalStatus {
  1905          pending,
  1906          pass,
  1907          cancel
  1908      }
  1909  
  1910      struct ProposalInfo {
  1911          /// @notice id
  1912          bytes4 id;
  1913          address proposer;
  1914          ProposalType pType;
  1915          uint256 deposit;
  1916          uint8 rate;
  1917          /// @notice name
  1918          string name;
  1919          string details;
  1920          uint256 initBlock;
  1921          address guarantee;
  1922          uint256 updateBlock;
  1923          ProposalStatus status;
  1924      }
  1925  
  1926      mapping(bytes4 => ProposalInfo) public proposalInfos;
  1927      mapping(address => bytes4[]) public proposals;
  1928  
  1929      EnumerableSet.Bytes32Set proposalsBytes;
  1930  
  1931      /// @notice Validators contract
  1932      IValidators public validators;
  1933  
  1934      event LogInitProposal(
  1935          bytes32 indexed id,
  1936          address indexed proposer,
  1937          uint256 block,
  1938          uint256 deposit,
  1939          uint256 rate
  1940      );
  1941      event LogGuarantee(
  1942          bytes32 indexed id,
  1943          address indexed guarantee,
  1944          uint256 block
  1945      );
  1946      event LogCancelProposal(
  1947          bytes32 indexed id,
  1948          address indexed proposer,
  1949          uint256 block
  1950      );
  1951      event LogUpdateProposal(
  1952          bytes32 indexed id,
  1953          address indexed proposer,
  1954          uint256 block,
  1955          uint256 deposit,
  1956          uint256 rate
  1957      );
  1958  
  1959      modifier onlyEffictiveValidator() {
  1960          require(
  1961              validators.isEffictiveValidator(msg.sender) ||
  1962                  validators.effictiveValsLength() == 0,
  1963              "Proposals: msg sender must be validator"
  1964          );
  1965          _;
  1966      }
  1967  
  1968      modifier onlyEffictiveProposal(bytes4 id) {
  1969          require(
  1970              block.number <=
  1971                  proposalInfos[id].initBlock +
  1972                      PROPOSAL_DURATION_EPOCHS *
  1973                      EPOCH_BLOCKS,
  1974              "Proposals: Proposal has expired"
  1975          );
  1976          _;
  1977      }
  1978  
  1979      modifier checkValidatorLength() {
  1980          require(
  1981              validators.effictiveValsLength() < MAX_VALIDATORS_COUNT,
  1982              "Proposals: length of the validator must be less than MAX_VALIDATORS_COUNT"
  1983          );
  1984          _;
  1985      }
  1986  
  1987      function initialize(address _validator) public onlySystem initializer {
  1988          validators = IValidators(_validator);
  1989      }
  1990  
  1991      /**
  1992       * @dev initProposal
  1993       */
  1994      function initProposal(
  1995          ProposalType pType,
  1996          uint8 rate,
  1997          string memory name,
  1998          string memory details
  1999      ) external payable nonReentrant checkValidatorLength {
  2000          require(
  2001              !validators.isEffictiveValidator(msg.sender),
  2002              "Proposals: The msg.sender can not be validator"
  2003          );
  2004          require(
  2005              !Address.isContract(msg.sender),
  2006              "Proposals: The msg.sender can not be contract address"
  2007          );
  2008          require(
  2009              bytes(details).length <= MAX_VALIDATOR_DETAIL_LENGTH,
  2010              "Proposals: Details is too long"
  2011          );
  2012          require(
  2013              bytes(name).length <= MAX_VALIDATOR_NAME_LENGTH,
  2014              "Proposals: name is too long"
  2015          );
  2016          require(
  2017              msg.value >= MIN_DEPOSIT,
  2018              "Proposals: Deposit must greater than MIN_DEPOSIT"
  2019          );
  2020          require(
  2021              rate >= MIN_RATE && rate <= MAX_RATE,
  2022              "Proposals: Rate must greater than MIN_RATE and less than MAX_RATE"
  2023          );
  2024          bytes4[] memory lastIds = proposals[msg.sender];
  2025          if (lastIds.length > 0) {
  2026              bytes4 lastId = lastIds[lastIds.length - 1];
  2027              require(
  2028                  proposalInfos[lastId].status != ProposalStatus.pending,
  2029                  "Proposals: The msg.sender's latest proposal is still in pending"
  2030              );
  2031          }
  2032          bytes4 id = bytes4(
  2033              keccak256(
  2034                  abi.encodePacked(
  2035                      msg.sender,
  2036                      msg.value,
  2037                      rate,
  2038                      name,
  2039                      details,
  2040                      block.number
  2041                  )
  2042              )
  2043          );
  2044          require(
  2045              proposalInfos[id].initBlock == 0,
  2046              "Proposals: Proposal already exists"
  2047          );
  2048          ProposalInfo memory proposal;
  2049          proposal.deposit = msg.value;
  2050          proposal.id = id;
  2051          proposal.details = details;
  2052          proposal.name = name;
  2053          proposal.initBlock = block.number;
  2054          proposal.proposer = msg.sender;
  2055          proposal.pType = pType;
  2056          proposal.status = ProposalStatus.pending;
  2057          proposal.rate = rate;
  2058          proposalInfos[id] = proposal;
  2059          proposals[address(msg.sender)].push(id);
  2060          proposalsBytes.add(id);
  2061          emit LogInitProposal(id, msg.sender, block.number, msg.value, rate);
  2062      }
  2063  
  2064      /**
  2065       * @dev guarantee
  2066       */
  2067      function guarantee(bytes4 id)
  2068          external
  2069          nonReentrant
  2070          onlyEffictiveValidator
  2071          onlyEffictiveProposal(id)
  2072      {
  2073          require(
  2074              proposalInfos[id].initBlock != 0,
  2075              "Proposals: proposal not exist"
  2076          );
  2077          require(
  2078              proposalInfos[id].status == ProposalStatus.pending,
  2079              "Proposals: The status of proposal must be pending"
  2080          );
  2081          proposalInfos[id].updateBlock = block.number;
  2082          proposalInfos[id].guarantee = msg.sender;
  2083          validators.addValidatorFromProposal{value: proposalInfos[id].deposit}(
  2084              proposalInfos[id].proposer,
  2085              proposalInfos[id].deposit,
  2086              proposalInfos[id].rate,
  2087              proposalInfos[id].name,
  2088              proposalInfos[id].details
  2089          );
  2090          proposalInfos[id].status = ProposalStatus.pass;
  2091          emit LogGuarantee(id, msg.sender, block.number);
  2092      }
  2093  
  2094      /**
  2095       * @dev updateProposal
  2096       */
  2097      function updateProposal(
  2098          bytes4 id,
  2099          uint8 rate,
  2100          uint256 deposit,
  2101          string memory name,
  2102          string memory details
  2103      ) external payable nonReentrant onlyEffictiveProposal(id) {
  2104          require(
  2105              proposalInfos[id].initBlock != 0,
  2106              "Proposals: proposal not exist"
  2107          );
  2108          require(
  2109              proposalInfos[id].proposer == msg.sender,
  2110              "Proposals: not proposer"
  2111          );
  2112          require(
  2113              proposalInfos[id].status == ProposalStatus.pending,
  2114              "Proposals: The status of proposal must be pending"
  2115          );
  2116          require(
  2117              bytes(name).length <= MAX_VALIDATOR_NAME_LENGTH,
  2118              "Proposals: name is too long"
  2119          );
  2120          require(
  2121              bytes(details).length <= MAX_VALIDATOR_DETAIL_LENGTH,
  2122              "Proposals: details is too long"
  2123          );
  2124          require(
  2125              deposit >= MIN_DEPOSIT,
  2126              "Proposals: deposit must greater than MIN_DEPOSIT"
  2127          );
  2128          require(
  2129              rate >= MIN_RATE && rate <= MAX_RATE,
  2130              "Proposals: rate must greater than MIN_RATE and less than MAX_RATE"
  2131          );
  2132          uint256 lastDeposit = proposalInfos[id].deposit;
  2133          if (lastDeposit > deposit) {
  2134              address payable receiver = payable(address(msg.sender));
  2135              receiver.transfer(lastDeposit - deposit);
  2136          } else if (lastDeposit < deposit) {
  2137              require(
  2138                  deposit - lastDeposit == msg.value,
  2139                  "Proposals: msg value not true"
  2140              );
  2141          } else {
  2142              if (msg.value != 0) {
  2143                  address payable receiver = payable(address(msg.sender));
  2144                  receiver.transfer(msg.value);
  2145              }
  2146          }
  2147          proposalInfos[id].deposit = deposit;
  2148          proposalInfos[id].rate = rate;
  2149          proposalInfos[id].updateBlock = block.number;
  2150          proposalInfos[id].name = name;
  2151          proposalInfos[id].details = details;
  2152          emit LogUpdateProposal(id, msg.sender, block.number, deposit, rate);
  2153      }
  2154  
  2155      /**
  2156       * @dev cancelProposal
  2157       */
  2158      function cancelProposal(bytes4 id) external nonReentrant {
  2159          require(
  2160              proposalInfos[id].initBlock != 0,
  2161              "Proposals: proposal not exist"
  2162          );
  2163          require(
  2164              proposalInfos[id].proposer == msg.sender,
  2165              "Proposals: not proposer"
  2166          );
  2167          require(
  2168              proposalInfos[id].status == ProposalStatus.pending,
  2169              "Proposals: The status of proposal must be pending"
  2170          );
  2171          proposalInfos[id].updateBlock = block.number;
  2172          address payable receiver = payable(address(msg.sender));
  2173          receiver.transfer(proposalInfos[id].deposit);
  2174          proposalInfos[id].status = ProposalStatus.cancel;
  2175          emit LogCancelProposal(id, msg.sender, block.number);
  2176      }
  2177  
  2178      function allProposals(uint256 page, uint256 size)
  2179          public
  2180          view
  2181          returns (ProposalInfo[] memory)
  2182      {
  2183          require(page > 0 && size > 0, "Proposals: Requests param error");
  2184          uint256 start = (page - 1) * size;
  2185          if (proposalsBytes.length() < start) {
  2186              size = 0;
  2187          } else {
  2188              uint256 length = proposalsBytes.length() - start;
  2189              if (length < size) {
  2190                  size = length;
  2191              }
  2192          }
  2193  
  2194          ProposalInfo[] memory proposalDir = new ProposalInfo[](size);
  2195          for (uint256 i = 0; i < size; i++) {
  2196              proposalDir[i] = proposalInfos[
  2197                  bytes4(proposalsBytes.at(i + start))
  2198              ];
  2199          }
  2200          return proposalDir;
  2201      }
  2202  
  2203      function allProposalSets(uint256 page, uint256 size)
  2204          public
  2205          view
  2206          returns (bytes4[] memory)
  2207      {
  2208          require(page > 0 && size > 0, "Proposals: Requests param error");
  2209          uint256 start = (page - 1) * size;
  2210          if (proposalsBytes.length() < start) {
  2211              size = 0;
  2212          } else {
  2213              uint256 length = proposalsBytes.length() - start;
  2214              if (length < size) {
  2215                  size = length;
  2216              }
  2217          }
  2218          bytes4[] memory proposalDir = new bytes4[](size);
  2219          for (uint256 i = 0; i < size; i++) {
  2220              proposalDir[i] = bytes4(proposalsBytes.at(i + start));
  2221          }
  2222          return proposalDir;
  2223      }
  2224  
  2225      function addressProposals(
  2226          address val,
  2227          uint256 page,
  2228          uint256 size
  2229      ) public view returns (ProposalInfo[] memory) {
  2230          require(page > 0 && size > 0, "Proposals: Requests param error");
  2231          bytes4[] memory addressProposalIds = proposals[val];
  2232          uint256 start = (page - 1) * size;
  2233          if (addressProposalIds.length < start) {
  2234              size = 0;
  2235          } else {
  2236              uint256 length = addressProposalIds.length - start;
  2237              if (length < size) {
  2238                  size = length;
  2239              }
  2240          }
  2241  
  2242          ProposalInfo[] memory proposalDir = new ProposalInfo[](size);
  2243          for (uint256 i = 0; i < size; i++) {
  2244              proposalDir[i] = proposalInfos[addressProposalIds[i + start]];
  2245          }
  2246          return proposalDir;
  2247      }
  2248  
  2249      function addressProposalSets(
  2250          address val,
  2251          uint256 page,
  2252          uint256 size
  2253      ) public view returns (bytes4[] memory) {
  2254          require(page > 0 && size > 0, "Proposals: Requests param error");
  2255          bytes4[] memory addressProposalIds = proposals[val];
  2256          uint256 start = (page - 1) * size;
  2257          if (addressProposalIds.length < start) {
  2258              size = 0;
  2259          } else {
  2260              uint256 length = addressProposalIds.length - start;
  2261              if (length < size) {
  2262                  size = length;
  2263              }
  2264          }
  2265  
  2266          bytes4[] memory proposalDir = new bytes4[](size);
  2267          for (uint256 i = 0; i < size; i++) {
  2268              proposalDir[i] = addressProposalIds[i + start];
  2269          }
  2270          return proposalDir;
  2271      }
  2272  
  2273      function proposalCount() public view returns (uint256) {
  2274          return proposalsBytes.length();
  2275      }
  2276  
  2277      function addressProposalCount(address val) public view returns (uint256) {
  2278          return proposals[val].length;
  2279      }
  2280  
  2281  }