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