Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Governor: Sequential Proposal Ids #5290

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

arr00
Copy link
Contributor

@arr00 arr00 commented Nov 1, 2024

Alternative solution to #5280

PR Checklist

  • Tests
  • Documentation
  • Changeset entry (run npx changeset add)

Copy link

changeset-bot bot commented Nov 1, 2024

🦋 Changeset detected

Latest commit: a04b47f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openzeppelin-solidity Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@arr00 arr00 mentioned this pull request Nov 18, 2024
3 tasks
@arr00 arr00 changed the title Sequential Proposal Ids Alt Governor: Sequential Proposal Ids Nov 18, 2024
@Amxx Amxx added this to the 5.3 milestone Nov 18, 2024
test/helpers/governance.js Outdated Show resolved Hide resolved
@arr00 arr00 requested review from frangio and Amxx November 22, 2024 16:24
}

/**
* @dev Internal function to set the sequential proposal ID for the next proposal. This is helpful for transitioning from another governing system.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a big caveat about decreasing the proposal count. I'd consider enforcing it in a require statement too, not sure if there are significant downsides to that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use-case that @arr00 metionned that someone may set the count to type(uint256).max to (temporarily) disable proposing until the correct number is set.

IMO that usecase (prevent any proposal from being submitted could be more cleanly done using the proposal threshold).

This is the require I proposed: #5290 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like to get @wildmolasses thoughts here. I'm leaning towards pushing the above approach of just using the proposal threshold.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'd keep that use case separate. But I do think it's a concern if setting the count to the max uint permanently blocks the governor from functioning... So this is why I'm not all in on enforcing that the update is an increase. A safer thing would be to allow increases of some reasonable size (like uint32), it seems arbitrary but I think it works.

@OpenZeppelin OpenZeppelin deleted a comment from 19714 Nov 25, 2024
@@ -212,6 +212,16 @@ interface IGovernor is IERC165, IERC6372 {
bytes32 descriptionHash
) external pure returns (uint256);

/**
* @dev Function used to get the proposal id from the proposal details
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @dev Function used to get the proposal id from the proposal details
* @dev Function used to get the proposal id from the proposal details.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're missing another check to mention the new getProposalId function

_proposalCount = newProposalCount;
}

function proposalCount() public view virtual returns (uint256) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to document this getter. Also, I'd put it up before the _propose function

}

/**
* @dev Internal function to set the current proposal count--the next proposal id will be `newProposalCount` + 1.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this sentence.

Suggested change
* @dev Internal function to set the current proposal count--the next proposal id will be `newProposalCount` + 1.
* @dev Internal function to set the current proposal count--the next proposal id will be `newProposalCount` + 1.

*
* May only call this function if the current proposal count is 0.
*/
function _setProposalCount(uint256 newProposalCount) internal virtual {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the purpose of including this function is to allow DAOs that are upgrading to set an initial proposal count in their initializers. If this is the case, I think this should be documented somewhere


import {Governor} from "../Governor.sol";

abstract contract GovernorSequentialProposalId is Governor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're missing NatSpec here

return storedProposalId;
}

function _propose(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing NatSpec here too

Comment on lines +11 to +14
/**
* @dev The proposal count may only be set if the current proposal count is 0 in {_setProposalCount}.
*/
error GovernorCanNotSetProposalCount();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rename it "uninitialized" since it better indicates what's wrong. Also, it goes well with the change I'm proposing to rename {_setProposalCount} to {_initializeProposalCount}. I think that instead of explaining the error literally, we should give a hint to solve it.

Suggested change
/**
* @dev The proposal count may only be set if the current proposal count is 0 in {_setProposalCount}.
*/
error GovernorCanNotSetProposalCount();
/**
* @dev The proposal count may only be set if the current proposal count is uninitialized.
*/
error GovernorUninitializedProposalCount();

*
* May only call this function if the current proposal count is 0.
*/
function _setProposalCount(uint256 newProposalCount) internal virtual {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be in favor of changing this function's name to indicate better what to do with it. In this case, it suggests developers that it should be used within an initializer.

Suggested change
function _setProposalCount(uint256 newProposalCount) internal virtual {
function _initializeProposalCount(uint256 newProposalCount) internal virtual {

Comment on lines +90 to +118
Governor_5_3: [
'name()',
'version()',
'COUNTING_MODE()',
'hashProposal(address[],uint256[],bytes[],bytes32)',
'getProposalId(address[],uint256[],bytes[],bytes32)',
'state(uint256)',
'proposalThreshold()',
'proposalSnapshot(uint256)',
'proposalDeadline(uint256)',
'proposalProposer(uint256)',
'proposalEta(uint256)',
'proposalNeedsQueuing(uint256)',
'votingDelay()',
'votingPeriod()',
'quorum(uint256)',
'getVotes(address,uint256)',
'getVotesWithParams(address,uint256,bytes)',
'hasVoted(uint256,address)',
'propose(address[],uint256[],bytes[],string)',
'queue(address[],uint256[],bytes[],bytes32)',
'execute(address[],uint256[],bytes[],bytes32)',
'cancel(address[],uint256[],bytes[],bytes32)',
'castVote(uint256,uint8)',
'castVoteWithReason(uint256,uint8,string)',
'castVoteWithReasonAndParams(uint256,uint8,string,bytes)',
'castVoteBySig(uint256,uint8,address,bytes)',
'castVoteWithReasonAndParamsBySig(uint256,uint8,address,string,bytes,bytes)',
],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really a fan of repeating all this interface, I'd look for a way to reuse it easily

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants