Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
ef52cdc
Remove the GovernorCompatibilyBravo module in favor of the simpler Go…
Amxx Jun 16, 2023
37f33a8
Update contracts/governance/README.adoc
Amxx Jun 16, 2023
0eb90ca
Apply suggestions from code review
Amxx Jun 20, 2023
fb35e92
wip
Amxx Jun 28, 2023
841c80d
Merge remote-tracking branch 'upstream' into feature/Governor-storage
Amxx Jun 28, 2023
4b97eb4
refactor state checking
Amxx Jun 28, 2023
0f89b6a
update docs
Amxx Jun 28, 2023
1d7e28c
fix lint
Amxx Jun 28, 2023
79ad539
_queue returns bool
Amxx Jun 29, 2023
c1a6eee
add changeset
Amxx Jun 29, 2023
51b37ec
bool → eta
Amxx Jun 29, 2023
f527b69
minimize change
Amxx Jun 29, 2023
1d60a50
split propose into public + internal
Amxx Jun 29, 2023
67f808a
split internals function
Amxx Jun 29, 2023
9b76c86
Update contracts/governance/extensions/GovernorStorage.sol
Amxx Jun 29, 2023
caf1fe8
wip
Amxx Jun 30, 2023
30eb76c
Merge remote-tracking branch 'upstream' into feature/Governor-storage
Amxx Jun 30, 2023
44e23cc
fix lint
Amxx Jul 3, 2023
18c1e35
test GovernorStorage
Amxx Jul 3, 2023
35d6359
coverage
Amxx Jul 3, 2023
aeae17e
lint
Amxx Jul 3, 2023
d4f858e
Merge remote-tracking branch 'upstream' into feature/Governor-storage
Amxx Jul 3, 2023
ce87721
move proposalEta to core
Amxx Jul 3, 2023
57cad90
Merge branch 'master' into feature/Governor-storage
Amxx Jul 5, 2023
8b7788b
fix lint
Amxx Jul 5, 2023
e7d2123
Merge remote-tracking branch 'upstream' into feature/Governor-storage
Amxx Jul 7, 2023
f2d55b0
Merge branch 'master' into feature/Governor-storage
ernestognw Jul 19, 2023
a67ce0e
remove proposalId from the internal function. It is now computed inte…
Amxx Jul 25, 2023
c8717b6
Merge branch 'master' into feature/Governor-storage
Amxx Jul 27, 2023
1b7a395
improve docs
frangio Jul 28, 2023
b97a4b7
rename implemented -> queued
frangio Jul 28, 2023
b828ced
rename _{queue,execute}Calls to _do{Queue,Execute}
frangio Jul 28, 2023
899b14b
typo
frangio Jul 28, 2023
edd9c35
edit docs section on GovStorage
frangio Jul 28, 2023
869836f
fix timelock id
frangio Jul 28, 2023
0091b82
remove proposalId and add descriptionHash to return values
frangio Jul 28, 2023
331f8e1
revert on unknown proposalId
frangio Jul 28, 2023
d44e090
lint
frangio Jul 29, 2023
ef1c20f
remove GovernorCompatibilityBravo.test.js
frangio Jul 29, 2023
11ca422
rename getters
frangio Jul 29, 2023
977083a
update changeset
frangio Jul 29, 2023
8084aa3
update changeset
frangio Jul 29, 2023
5645ec8
fix test helpers & remove clock from the governor interface id
Amxx Jul 31, 2023
9d2ac8b
_doQueue returns eta only
Amxx Jul 31, 2023
ccd0d47
Update docs/modules/ROOT/pages/governance.adoc
Amxx Jul 31, 2023
d3d2396
merge _proposals and _proposalsExtra mappings
Amxx Jul 31, 2023
440cedc
Apply suggestions from code review
frangio Aug 1, 2023
bdddeda
switch to custom error and add tests
frangio Aug 1, 2023
b2445f8
Batch GovernorStorage transactions setup
ernestognw Aug 1, 2023
2a8dfb3
improve _cancel docs
frangio Aug 1, 2023
02e43ff
add proposalThreshold in IGovernor
frangio Aug 1, 2023
92589ff
improve definition of ETA
frangio Aug 1, 2023
e313b71
remove redundant docs
frangio Aug 1, 2023
caf04b2
edit docs for queue
frangio Aug 1, 2023
b01dad5
add note on possible revert in _queue
frangio Aug 1, 2023
ec55fe1
Merge remote-tracking branch 'upstream/master' into feature/Governor-…
frangio Aug 1, 2023
6b352c4
add missing await
frangio Aug 1, 2023
6f99bc9
fix variable
frangio Aug 1, 2023
62f6fd6
Revert "add missing await"
frangio Aug 1, 2023
037831e
rename _do{Queue,Execute} to _{queue,execute}Operations
frangio Aug 1, 2023
5e74069
lint
frangio Aug 1, 2023
8cb38ed
remove internal _queue and _execute
frangio Aug 3, 2023
d861ec1
make governor into interface
frangio Aug 1, 2023
f9240de
turn IGovernor into interface
frangio Aug 3, 2023
9e7f04e
lint
frangio Aug 3, 2023
d1d8e83
lint
frangio Aug 3, 2023
ae58b64
fix docs
frangio Aug 3, 2023
d2e54af
Remove clock and CLOCK_Mode from IGovernor
Amxx Aug 3, 2023
1853702
document memory/storage insonsistency has beeing the result of gas co…
Amxx Aug 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
bool → eta
  • Loading branch information
Amxx committed Jun 29, 2023
commit 51b37ec11b22d0d10a68cf9a7e567a597c09864d
2 changes: 1 addition & 1 deletion .changeset/brave-lobsters-punch.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'openzeppelin-solidity': major
---

`Governor`: Add a public `queue` and an internal `_queue` function in the governor core. Module that implemement queuing are expected to override the internal one.
`Governor`: Add a public `queue` and an internal `_queue` function in the governor core. Module that implement queuing are expected to override the internal one.
42 changes: 13 additions & 29 deletions contracts/governance/Governor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,27 +96,8 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
bytes4 governorCancelId = this.cancel.selector ^ this.proposalProposer.selector;

bytes4 governorParamsId = this.castVoteWithReasonAndParams.selector ^
this.castVoteWithReasonAndParamsBySig.selector ^
this.getVotesWithParams.selector;

// The original interface id in v4.3.
bytes4 governor43Id = type(IGovernor).interfaceId ^
type(IERC6372).interfaceId ^
governorCancelId ^
governorParamsId;

// An updated interface id in v4.6, with params added.
bytes4 governor46Id = type(IGovernor).interfaceId ^ type(IERC6372).interfaceId ^ governorCancelId;

// For the updated interface id in v4.9, we use governorCancelId directly.

return
interfaceId == governor43Id ||
interfaceId == governor46Id ||
interfaceId == governorCancelId ||
interfaceId == type(IGovernor).interfaceId ||
interfaceId == type(IERC1155Receiver).interfaceId ||
super.supportsInterface(interfaceId);
}
Expand Down Expand Up @@ -321,19 +302,22 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
}

/**
* @dev See {IGovernorTimelock-queue}.
* @dev See {IGovernor-queue}.
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual returns (uint256 proposalId) {
) public virtual override returns (uint256 proposalId) {
proposalId = hashProposal(targets, values, calldatas, descriptionHash);
_validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded));

if (!_queue(proposalId, targets, values, calldatas, descriptionHash)) {
uint256 eta = _queue(proposalId, targets, values, calldatas, descriptionHash);
if (eta == 0) {
revert GovernorQueueNotImplemented();
} else {
emit ProposalQueued(proposalId, eta);
}
}

Expand Down Expand Up @@ -432,20 +416,20 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receive
}

/**
* @dev Internal queuing mechanism. This is empty by default, and must be overriden to implement queuing.
* @dev Internal queuing mechanism. This is empty by default, and must be overridden to implement queuing.
*
* This function returns a boolean that describing weither a queuing logic is implemented or not. This function
* returns false by default, which causes the public {queue} to revert. When overriding this, the overriden
* version should discard the value returned by the super call and return true instead.
* This function returns a timestamp that describes the expected eta for execution. If the returned value is 0
* (which is the default value), the core will consider queueing to not be implemented, and the public {queue}
* function will revert.
*/
function _queue(
uint256 /* proposalId */,
address[] memory /* targets */,
uint256[] memory /* values */,
bytes[] memory /* calldatas */,
bytes32 /*descriptionHash*/
) internal virtual returns (bool enabled) {
return false;
) internal virtual returns (uint256 eta) {
return 0;
}

/**
Expand Down
26 changes: 23 additions & 3 deletions contracts/governance/IGovernor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,20 @@ abstract contract IGovernor is IERC165, IERC6372 {
);

/**
* @dev Emitted when a proposal is canceled.
* @dev Emitted when a proposal is queued.
*/
event ProposalCanceled(uint256 proposalId);
event ProposalQueued(uint256 proposalId, uint256 eta);

/**
* @dev Emitted when a proposal is executed.
*/
event ProposalExecuted(uint256 proposalId);

/**
* @dev Emitted when a proposal is canceled.
*/
event ProposalCanceled(uint256 proposalId);

/**
* @dev Emitted when a vote is cast without params.
*
Expand Down Expand Up @@ -295,9 +300,24 @@ abstract contract IGovernor is IERC165, IERC6372 {
) public virtual returns (uint256 proposalId);

/**
* @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
* @dev Queue a proposal. Some governors require this step to be performed before execution can happens. Some
* governors do not. Queuing a proposal requires the quorum to be reached, the vote to be successful, and the
* deadline to be reached.
*
* Emits a {ProposalQueued} event.
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual returns (uint256 proposalId);

/**
* @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
* deadline to be reached. Depending on the governor it might also be required that the proposal was queued and
* that some delay passed.
*
* Emits a {ProposalExecuted} event.
*
* Note: some module can modify the requirements for execution, for example by adding an additional timelock.
Expand Down
24 changes: 6 additions & 18 deletions contracts/governance/extensions/GovernorTimelockCompound.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,6 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
return _proposalEta[proposalId];
}

/**
* @dev {IGovernor-queue} override resolution
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual override(IGovernorTimelock, Governor) returns (uint256) {
return super.queue(targets, values, calldatas, descriptionHash);
}

/**
* @dev Function to queue a proposal to the timelock.
*/
Expand All @@ -101,10 +89,12 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override returns (bool) {
super._queue(proposalId, targets, values, calldatas, descriptionHash);
) internal virtual override returns (uint256) {
uint256 eta = Math.max(
super._queue(proposalId, targets, values, calldatas, descriptionHash),
block.timestamp + _timelock.delay()
);

uint256 eta = block.timestamp + _timelock.delay();
_proposalEta[proposalId] = eta;

for (uint256 i = 0; i < targets.length; ++i) {
Expand All @@ -114,9 +104,7 @@ abstract contract GovernorTimelockCompound is IGovernorTimelock, Governor {
_timelock.queueTransaction(targets[i], values[i], "", calldatas[i], eta);
}

emit ProposalQueued(proposalId, eta);

return true;
return eta;
}

/**
Expand Down
20 changes: 3 additions & 17 deletions contracts/governance/extensions/GovernorTimelockControl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,6 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
return eta == 1 ? 0 : eta; // _DONE_TIMESTAMP (1) should be replaced with a 0 value
}

/**
* @dev {IGovernor-queue} override resolution
*/
function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual override(IGovernorTimelock, Governor) returns (uint256) {
return super.queue(targets, values, calldatas, descriptionHash);
}

/**
* @dev Function to queue a proposal to the timelock.
*/
Expand All @@ -107,16 +95,14 @@ abstract contract GovernorTimelockControl is IGovernorTimelock, Governor {
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal virtual override returns (bool) {
super._queue(proposalId, targets, values, calldatas, descriptionHash);
) internal virtual override returns (uint256) {
uint256 superEta = super._queue(proposalId, targets, values, calldatas, descriptionHash);

uint256 delay = _timelock.getMinDelay();
_timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash);
_timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay);

emit ProposalQueued(proposalId, block.timestamp + delay);

return true;
return Math.max(superEta, block.timestamp + delay);
}

/**
Expand Down
9 changes: 0 additions & 9 deletions contracts/governance/extensions/IGovernorTimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,7 @@ abstract contract IGovernorTimelock is IGovernor {
*/
error GovernorAlreadyQueuedProposal(uint256 proposalId);

event ProposalQueued(uint256 proposalId, uint256 eta);

function timelock() public view virtual returns (address);

function proposalEta(uint256 proposalId) public view virtual returns (uint256);

function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public virtual returns (uint256 proposalId);
}
11 changes: 1 addition & 10 deletions contracts/mocks/docs/governance/MyGovernor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,6 @@ contract MyGovernor is
return super.propose(targets, values, calldatas, description);
}

function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public override(Governor, GovernorTimelockControl) returns (uint256) {
return super.queue(targets, values, calldatas, descriptionHash);
}

function cancel(
address[] memory targets,
uint256[] memory values,
Expand All @@ -70,7 +61,7 @@ contract MyGovernor is
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (bool enabled) {
) internal override(Governor, GovernorTimelockControl) returns (uint256) {
return super._queue(proposalId, targets, values, calldatas, descriptionHash);
}

Expand Down
11 changes: 1 addition & 10 deletions contracts/mocks/governance/GovernorTimelockCompoundMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,13 @@ abstract contract GovernorTimelockCompoundMock is
return super.proposalThreshold();
}

function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public override(Governor, GovernorTimelockCompound) returns (uint256) {
return super.queue(targets, values, calldatas, descriptionHash);
}

function _queue(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockCompound) returns (bool enabled) {
) internal override(Governor, GovernorTimelockCompound) returns (uint256) {
return super._queue(proposalId, targets, values, calldatas, descriptionHash);
}

Expand Down
11 changes: 1 addition & 10 deletions contracts/mocks/governance/GovernorTimelockControlMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,13 @@ abstract contract GovernorTimelockControlMock is
return super.proposalThreshold();
}

function queue(
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) public override(Governor, GovernorTimelockControl) returns (uint256) {
return super.queue(targets, values, calldatas, descriptionHash);
}

function _queue(
uint256 proposalId,
address[] memory targets,
uint256[] memory values,
bytes[] memory calldatas,
bytes32 descriptionHash
) internal override(Governor, GovernorTimelockControl) returns (bool enabled) {
) internal override(Governor, GovernorTimelockControl) returns (uint256) {
return super._queue(proposalId, targets, values, calldatas, descriptionHash);
}

Expand Down
2 changes: 1 addition & 1 deletion test/governance/Governor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ contract('Governor', function (accounts) {
);
});

shouldSupportInterfaces(['ERC165', 'ERC1155Receiver', 'Governor', 'GovernorWithParams', 'GovernorCancel']);
shouldSupportInterfaces(['ERC165', 'ERC1155Receiver', 'Governor']);
shouldBehaveLikeEIP6372(mode);

it('deployment check', async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ contract('GovernorTimelockCompound', function (accounts) {
);
});

shouldSupportInterfaces(['ERC165', 'Governor', 'GovernorWithParams', 'GovernorTimelock']);
shouldSupportInterfaces(['ERC165', 'Governor', 'GovernorTimelock']);

it("doesn't accept ether transfers", async function () {
await expectRevert.unspecified(web3.eth.sendTransaction({ from: owner, to: this.mock.address, value: 1 }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ contract('GovernorTimelockControl', function (accounts) {
);
});

shouldSupportInterfaces(['ERC165', 'Governor', 'GovernorWithParams', 'GovernorTimelock']);
Copy link
Member

Choose a reason for hiding this comment

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

I see why it makes sense to remove this check since we're already testing Governor and this contract inherits from it, but I'd rather keep this check to make the tests independent between each other.

shouldSupportInterfaces(['ERC165', 'Governor', 'GovernorTimelock']);

it("doesn't accept ether transfers", async function () {
await expectRevert.unspecified(web3.eth.sendTransaction({ from: owner, to: this.mock.address, value: 1 }));
Expand Down
27 changes: 6 additions & 21 deletions test/utils/introspection/SupportsInterface.behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,46 +52,31 @@ const INTERFACES = {
Governor: [
'name()',
'version()',
'clock()', // part of ERC-6372, but redeclared as public
'CLOCK_MODE()', // part of ERC-6372, but redeclared as public
'COUNTING_MODE()',
'hashProposal(address[],uint256[],bytes[],bytes32)',
'state(uint256)',
'proposalSnapshot(uint256)',
'proposalDeadline(uint256)',
'votingDelay()',
'votingPeriod()',
'quorum(uint256)',
'getVotes(address,uint256)',
'hasVoted(uint256,address)',
'propose(address[],uint256[],bytes[],string)',
'execute(address[],uint256[],bytes[],bytes32)',
'castVote(uint256,uint8)',
'castVoteWithReason(uint256,uint8,string)',
'castVoteBySig(uint256,uint8,uint8,bytes32,bytes32)',
],
GovernorWithParams: [
'name()',
'version()',
'COUNTING_MODE()',
'hashProposal(address[],uint256[],bytes[],bytes32)',
'state(uint256)',
'proposalSnapshot(uint256)',
'proposalDeadline(uint256)',
'proposalProposer(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,uint8,bytes32,bytes32)',
'castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32)',
],
GovernorCancel: ['proposalProposer(uint256)', 'cancel(address[],uint256[],bytes[],bytes32)'],
GovernorTimelock: ['timelock()', 'proposalEta(uint256)', 'queue(address[],uint256[],bytes[],bytes32)'],
GovernorTimelock: ['timelock()', 'proposalEta(uint256)'],
ERC2981: ['royaltyInfo(uint256,uint256)'],
};

Expand Down