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