GovernorSequentialProposalId.sol 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import {Governor} from "../Governor.sol";
  4. /**
  5. * @dev Extension of {Governor} that changes the numbering of proposal ids from the default hash-based approach to
  6. * sequential ids.
  7. */
  8. abstract contract GovernorSequentialProposalId is Governor {
  9. uint256 private _latestProposalId;
  10. mapping(uint256 proposalHash => uint256 proposalId) private _proposalIds;
  11. /**
  12. * @dev The {latestProposalId} may only be initialized if it hasn't been set yet
  13. * (through initialization or the creation of a proposal).
  14. */
  15. error GovernorAlreadyInitializedLatestProposalId();
  16. /**
  17. * @dev See {IGovernor-getProposalId}.
  18. */
  19. function getProposalId(
  20. address[] memory targets,
  21. uint256[] memory values,
  22. bytes[] memory calldatas,
  23. bytes32 descriptionHash
  24. ) public view virtual override returns (uint256) {
  25. uint256 proposalHash = hashProposal(targets, values, calldatas, descriptionHash);
  26. uint256 storedProposalId = _proposalIds[proposalHash];
  27. if (storedProposalId == 0) {
  28. revert GovernorNonexistentProposal(0);
  29. }
  30. return storedProposalId;
  31. }
  32. /**
  33. * @dev Returns the latest proposal id. A return value of 0 means no proposals have been created yet.
  34. */
  35. function latestProposalId() public view virtual returns (uint256) {
  36. return _latestProposalId;
  37. }
  38. /**
  39. * @dev See {IGovernor-_propose}.
  40. * Hook into the proposing mechanism to increment proposal count.
  41. */
  42. function _propose(
  43. address[] memory targets,
  44. uint256[] memory values,
  45. bytes[] memory calldatas,
  46. string memory description,
  47. address proposer
  48. ) internal virtual override returns (uint256) {
  49. uint256 proposalHash = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
  50. uint256 storedProposalId = _proposalIds[proposalHash];
  51. if (storedProposalId == 0) {
  52. _proposalIds[proposalHash] = ++_latestProposalId;
  53. }
  54. return super._propose(targets, values, calldatas, description, proposer);
  55. }
  56. /**
  57. * @dev Internal function to set the {latestProposalId}. This function is helpful when transitioning
  58. * from another governance system. The next proposal id will be `newLatestProposalId` + 1.
  59. *
  60. * May only call this function if the current value of {latestProposalId} is 0.
  61. */
  62. function _initializeLatestProposalId(uint256 newLatestProposalId) internal virtual {
  63. if (_latestProposalId != 0) {
  64. revert GovernorAlreadyInitializedLatestProposalId();
  65. }
  66. _latestProposalId = newLatestProposalId;
  67. }
  68. }