GovernorPreventLateQuorum.sol 4.3 KB

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