GovernorPreventLateQuorumUpgradeable.sol 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.5.0-rc.0) (governance/extensions/GovernorPreventLateQuorum.sol)
  3. pragma solidity ^0.8.0;
  4. import "../GovernorUpgradeable.sol";
  5. import "../../utils/math/MathUpgradeable.sol";
  6. import "../../proxy/utils/Initializable.sol";
  7. /**
  8. * @dev A module that ensures there is a minimum voting period after quorum is reached. This prevents a large voter from
  9. * swaying a vote and triggering quorum at the last minute, by ensuring there is always time for other voters to react
  10. * and try to oppose the decision.
  11. *
  12. * If a vote causes quorum to be reached, the proposal's voting period may be extended so that it does not end before at
  13. * least a given number of blocks have passed (the "vote extension" parameter). This parameter can be set by the
  14. * governance executor (e.g. through a governance proposal).
  15. *
  16. * _Available since v4.5._
  17. */
  18. abstract contract GovernorPreventLateQuorumUpgradeable is Initializable, GovernorUpgradeable {
  19. using SafeCastUpgradeable for uint256;
  20. using TimersUpgradeable for TimersUpgradeable.BlockNumber;
  21. uint64 private _voteExtension;
  22. mapping(uint256 => TimersUpgradeable.BlockNumber) private _extendedDeadlines;
  23. /// @dev Emitted when a proposal deadline is pushed back due to reaching quorum late in its voting period.
  24. event ProposalExtended(uint256 indexed proposalId, uint64 extendedDeadline);
  25. /// @dev Emitted when the {lateQuorumVoteExtension} parameter is changed.
  26. event LateQuorumVoteExtensionSet(uint64 oldVoteExtension, uint64 newVoteExtension);
  27. /**
  28. * @dev Initializes the vote extension parameter: the number of blocks that are required to pass since a proposal
  29. * reaches quorum until its voting period ends. If necessary the voting period will be extended beyond the one set
  30. * at proposal creation.
  31. */
  32. function __GovernorPreventLateQuorum_init(uint64 initialVoteExtension) internal onlyInitializing {
  33. __GovernorPreventLateQuorum_init_unchained(initialVoteExtension);
  34. }
  35. function __GovernorPreventLateQuorum_init_unchained(uint64 initialVoteExtension) internal onlyInitializing {
  36. _setLateQuorumVoteExtension(initialVoteExtension);
  37. }
  38. /**
  39. * @dev Returns the proposal deadline, which may have been extended beyond that set at proposal creation, if the
  40. * proposal reached quorum late in the voting period. See {Governor-proposalDeadline}.
  41. */
  42. function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) {
  43. return MathUpgradeable.max(super.proposalDeadline(proposalId), _extendedDeadlines[proposalId].getDeadline());
  44. }
  45. /**
  46. * @dev Casts a vote and detects if it caused quorum to be reached, potentially extending the voting period. See
  47. * {Governor-_castVote}.
  48. *
  49. * May emit a {ProposalExtended} event.
  50. */
  51. function _castVote(
  52. uint256 proposalId,
  53. address account,
  54. uint8 support,
  55. string memory reason
  56. ) internal virtual override returns (uint256) {
  57. uint256 result = super._castVote(proposalId, account, support, reason);
  58. TimersUpgradeable.BlockNumber storage extendedDeadline = _extendedDeadlines[proposalId];
  59. if (extendedDeadline.isUnset() && _quorumReached(proposalId)) {
  60. uint64 extendedDeadlineValue = block.number.toUint64() + lateQuorumVoteExtension();
  61. if (extendedDeadlineValue > proposalDeadline(proposalId)) {
  62. emit ProposalExtended(proposalId, extendedDeadlineValue);
  63. }
  64. extendedDeadline.setDeadline(extendedDeadlineValue);
  65. }
  66. return result;
  67. }
  68. /**
  69. * @dev Returns the current value of the vote extension parameter: the number of blocks that are required to pass
  70. * from the time a proposal reaches quorum until its voting period ends.
  71. */
  72. function lateQuorumVoteExtension() public view virtual returns (uint64) {
  73. return _voteExtension;
  74. }
  75. /**
  76. * @dev Changes the {lateQuorumVoteExtension}. This operation can only be performed by the governance executor,
  77. * generally through a governance proposal.
  78. *
  79. * Emits a {LateQuorumVoteExtensionSet} event.
  80. */
  81. function setLateQuorumVoteExtension(uint64 newVoteExtension) public virtual onlyGovernance {
  82. _setLateQuorumVoteExtension(newVoteExtension);
  83. }
  84. /**
  85. * @dev Changes the {lateQuorumVoteExtension}. This is an internal function that can be exposed in a public function
  86. * like {setLateQuorumVoteExtension} if another access control mechanism is needed.
  87. *
  88. * Emits a {LateQuorumVoteExtensionSet} event.
  89. */
  90. function _setLateQuorumVoteExtension(uint64 newVoteExtension) internal virtual {
  91. emit LateQuorumVoteExtensionSet(_voteExtension, newVoteExtension);
  92. _voteExtension = newVoteExtension;
  93. }
  94. /**
  95. * This empty reserved space is put in place to allow future versions to add new
  96. * variables without shifting down storage in the inheritance chain.
  97. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  98. */
  99. uint256[48] private __gap;
  100. }