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