GovernorVotesSuperQuorumFraction.sol 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v5.3.0-rc.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol)
  3. pragma solidity ^0.8.20;
  4. import {Governor} from "../Governor.sol";
  5. import {GovernorSuperQuorum} from "./GovernorSuperQuorum.sol";
  6. import {GovernorVotesQuorumFraction} from "./GovernorVotesQuorumFraction.sol";
  7. import {Math} from "../../utils/math/Math.sol";
  8. import {SafeCast} from "../../utils/math/SafeCast.sol";
  9. import {Checkpoints} from "../../utils/structs/Checkpoints.sol";
  10. /**
  11. * @dev Extension of {GovernorVotesQuorumFraction} with a super quorum expressed as a
  12. * fraction of the total supply. Proposals that meet the super quorum (and have a majority of for votes) advance to
  13. * the `Succeeded` state before the proposal deadline.
  14. */
  15. abstract contract GovernorVotesSuperQuorumFraction is GovernorVotesQuorumFraction, GovernorSuperQuorum {
  16. using Checkpoints for Checkpoints.Trace208;
  17. Checkpoints.Trace208 private _superQuorumNumeratorHistory;
  18. event SuperQuorumNumeratorUpdated(uint256 oldSuperQuorumNumerator, uint256 newSuperQuorumNumerator);
  19. /**
  20. * @dev The super quorum set is not valid as it exceeds the quorum denominator.
  21. */
  22. error GovernorInvalidSuperQuorumFraction(uint256 superQuorumNumerator, uint256 denominator);
  23. /**
  24. * @dev The super quorum set is not valid as it is smaller or equal to the quorum.
  25. */
  26. error GovernorInvalidSuperQuorumTooSmall(uint256 superQuorumNumerator, uint256 quorumNumerator);
  27. /**
  28. * @dev The quorum set is not valid as it exceeds the super quorum.
  29. */
  30. error GovernorInvalidQuorumTooLarge(uint256 quorumNumerator, uint256 superQuorumNumerator);
  31. /**
  32. * @dev Initialize super quorum as a fraction of the token's total supply.
  33. *
  34. * The super quorum is specified as a fraction of the token's total supply and has to
  35. * be greater than the quorum.
  36. */
  37. constructor(uint256 superQuorumNumeratorValue) {
  38. _updateSuperQuorumNumerator(superQuorumNumeratorValue);
  39. }
  40. /**
  41. * @dev Returns the current super quorum numerator.
  42. */
  43. function superQuorumNumerator() public view virtual returns (uint256) {
  44. return _superQuorumNumeratorHistory.latest();
  45. }
  46. /**
  47. * @dev Returns the super quorum numerator at a specific `timepoint`.
  48. */
  49. function superQuorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
  50. return _optimisticUpperLookupRecent(_superQuorumNumeratorHistory, timepoint);
  51. }
  52. /**
  53. * @dev Returns the super quorum for a `timepoint`, in terms of number of votes: `supply * numerator / denominator`.
  54. * See {GovernorSuperQuorum-superQuorum} for more details.
  55. */
  56. function superQuorum(uint256 timepoint) public view virtual override returns (uint256) {
  57. return Math.mulDiv(token().getPastTotalSupply(timepoint), superQuorumNumerator(timepoint), quorumDenominator());
  58. }
  59. /**
  60. * @dev Changes the super quorum numerator.
  61. *
  62. * Emits a {SuperQuorumNumeratorUpdated} event.
  63. *
  64. * Requirements:
  65. *
  66. * - Must be called through a governance proposal.
  67. * - New super quorum numerator must be smaller or equal to the denominator.
  68. * - New super quorum numerator must be greater than or equal to the quorum numerator.
  69. */
  70. function updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public virtual onlyGovernance {
  71. _updateSuperQuorumNumerator(newSuperQuorumNumerator);
  72. }
  73. /**
  74. * @dev Changes the super quorum numerator.
  75. *
  76. * Emits a {SuperQuorumNumeratorUpdated} event.
  77. *
  78. * Requirements:
  79. *
  80. * - New super quorum numerator must be smaller or equal to the denominator.
  81. * - New super quorum numerator must be greater than or equal to the quorum numerator.
  82. */
  83. function _updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) internal virtual {
  84. uint256 denominator = quorumDenominator();
  85. if (newSuperQuorumNumerator > denominator) {
  86. revert GovernorInvalidSuperQuorumFraction(newSuperQuorumNumerator, denominator);
  87. }
  88. uint256 quorumNumerator = quorumNumerator();
  89. if (newSuperQuorumNumerator < quorumNumerator) {
  90. revert GovernorInvalidSuperQuorumTooSmall(newSuperQuorumNumerator, quorumNumerator);
  91. }
  92. uint256 oldSuperQuorumNumerator = _superQuorumNumeratorHistory.latest();
  93. _superQuorumNumeratorHistory.push(clock(), SafeCast.toUint208(newSuperQuorumNumerator));
  94. emit SuperQuorumNumeratorUpdated(oldSuperQuorumNumerator, newSuperQuorumNumerator);
  95. }
  96. /**
  97. * @dev Overrides {GovernorVotesQuorumFraction-_updateQuorumNumerator} to ensure the super
  98. * quorum numerator is greater than or equal to the quorum numerator.
  99. */
  100. function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual override {
  101. // Ignoring check when the superQuorum was never set (construction sets quorum before superQuorum)
  102. if (_superQuorumNumeratorHistory.length() > 0) {
  103. uint256 superQuorumNumerator_ = superQuorumNumerator();
  104. if (newQuorumNumerator > superQuorumNumerator_) {
  105. revert GovernorInvalidQuorumTooLarge(newQuorumNumerator, superQuorumNumerator_);
  106. }
  107. }
  108. super._updateQuorumNumerator(newQuorumNumerator);
  109. }
  110. /// @inheritdoc GovernorSuperQuorum
  111. function state(
  112. uint256 proposalId
  113. ) public view virtual override(Governor, GovernorSuperQuorum) returns (ProposalState) {
  114. return super.state(proposalId);
  115. }
  116. }