-
Notifications
You must be signed in to change notification settings - Fork 12.1k
Add formal verification for the Governor system #4106
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
Draft
Amxx
wants to merge
72
commits into
master
Choose a base branch
from
fv/Governor
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 4 commits
Commits
Show all changes
72 commits
Select commit
Hold shift + click to select a range
1f5982b
starting to work on governor specifications
Amxx 5421355
test both modes
Amxx f35c824
fix specs
Amxx 9f39697
lint
Amxx ec82e2f
use micromatch
Amxx f44e26f
disable wip specs
Amxx 318cfd5
update
Amxx f71bc68
clean
Amxx 4b11b4d
codespell
Amxx c33e7bd
update governor specs
Amxx b320e1e
lint
Amxx e35daec
Merge branch 'master' into fv/Governor
Amxx 704e265
fix governor changes spec
Amxx e1120b9
try optimise GovernorStates
Amxx 728e2c8
fix
Amxx 397f4cd
filter functions that should revert
Amxx d2b5d15
Merge remote-tracking branch 'upstream/master' into fv/Governor
Amxx d788425
update
Amxx 0d4df89
add filter to improve prover perf
Amxx 198c4b7
update
Amxx 0874adb
spacing
Amxx 4ea73a8
add PreventLateQuorum specs
Amxx 50a13d5
uo
Amxx dfafd79
uo
Amxx 9655359
disable GovernorFunctions
Amxx 89ceb34
don't run GovernorFunctions in CI
Amxx 82bbdb2
codespell
Amxx d0b2595
fix options
Amxx 74f613f
fix specs
Amxx dd6a9ee
fix attempt
Amxx 7512b8e
missing diff
Amxx 06baea7
up
Amxx a355bf0
fix
Amxx dbb4a29
split function rules
Amxx 607268b
timeout
Amxx 3f79e26
update
Amxx 5ef4d20
more fixes ?
Amxx ddaf4bc
up
Amxx 5770dfb
wip
Amxx 1744132
Merge branch 'master' into fv/Governor
Amxx a64bb88
update
Amxx 67a00cc
disable specs we can't fix :/
Amxx ecec8a7
codespell
Amxx 7c62ed2
disable problematic rules
Amxx 8d02947
test function with both clocks
Amxx 42580f2
Merge branch 'master' into fv/Governor
Amxx 5e71c01
rename valid → sanity
Amxx e072521
fix harness
Amxx 5af9167
address PR comments
Amxx 8339187
fix
Amxx e928466
Do not run the FV workflow automatically on master
Amxx c8457ba
Merge branch 'master' of github.com:OpenZeppelin/openzeppelin-contracts
Amxx 0daafdb
fix harness
Amxx 6af1f18
merge master
Amxx f21451f
Merge branch 'master' into fv/Governor
Amxx 75d6f5a
move Governor.helpers.spec to helpers folder
Amxx 3d9ef78
fix import path
Amxx 2a6cceb
Fix early reporting of FV prover's output
Amxx 7c37ea0
fix rewrite
Amxx e83fdf0
trying to fix timeout
Amxx e856ebb
Merge branch 'CI/FV/urls' into fv/Governor
Amxx fd5f309
improve stateTransitionWait
Amxx df88ea3
fix lint
Amxx a97d3f5
codespell
Amxx 9a33b0d
split stateTransitionFn as multiple rules with requires
Amxx 3431624
up
Amxx c664f5f
try to simplify rules
Amxx e9779f8
Merge remote-tracking branch 'upstream' into fv/Governor
Amxx 2e1d0b3
fix spec file
Amxx 6d539e6
comment out rules that timeout
Amxx e9f23ab
Merge remote-tracking branch 'upstream' into fv/Governor
Amxx aaa5a5a
Merge branch 'master' into fv/Governor
Amxx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--- governance/Governor.sol 2023-03-07 10:48:47.730155491 +0100 | ||
+++ governance/Governor.sol 2023-03-10 10:13:31.926616811 +0100 | ||
@@ -216,6 +216,16 @@ | ||
return _proposals[proposalId].proposer; | ||
} | ||
|
||
+ // FV | ||
+ function _isExecuted(uint256 proposalId) internal view returns (bool) { | ||
+ return _proposals[proposalId].executed; | ||
+ } | ||
+ | ||
+ // FV | ||
+ function _isCanceled(uint256 proposalId) internal view returns (bool) { | ||
+ return _proposals[proposalId].canceled; | ||
+ } | ||
+ | ||
/** | ||
* @dev Amount of votes already cast passes the threshold limit. | ||
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "../patched/access/AccessControl.sol"; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "../patched/token/ERC20/ERC20.sol"; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "../patched/token/ERC20/extensions/ERC20Votes.sol"; | ||
|
||
contract ERC20VotesBlocknumberHarness is ERC20Votes { | ||
constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} | ||
|
||
function mint(address account, uint256 amount) external { | ||
_mint(account, amount); | ||
} | ||
|
||
function burn(address account, uint256 amount) external { | ||
_burn(account, amount); | ||
} | ||
|
||
// inspection | ||
function ckptFromBlock(address account, uint32 pos) public view returns (uint32) { | ||
return checkpoints(account, pos).fromBlock; | ||
} | ||
|
||
function ckptVotes(address account, uint32 pos) public view returns (uint224) { | ||
return checkpoints(account, pos).votes; | ||
} | ||
|
||
function maxSupply() public view returns (uint224) { | ||
return _maxSupply(); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "../patched/token/ERC20/extensions/ERC20Votes.sol"; | ||
|
||
contract ERC20VotesTimestampHarness is ERC20Votes { | ||
constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} | ||
|
||
function mint(address account, uint256 amount) external { | ||
_mint(account, amount); | ||
} | ||
|
||
function burn(address account, uint256 amount) external { | ||
_burn(account, amount); | ||
} | ||
|
||
// inspection | ||
function ckptFromBlock(address account, uint32 pos) public view returns (uint32) { | ||
return checkpoints(account, pos).fromBlock; | ||
} | ||
|
||
function ckptVotes(address account, uint32 pos) public view returns (uint224) { | ||
return checkpoints(account, pos).votes; | ||
} | ||
|
||
function maxSupply() public view returns (uint224) { | ||
return _maxSupply(); | ||
} | ||
|
||
// clock | ||
function clock() public view override returns (uint48) { | ||
return uint48(block.timestamp); | ||
} | ||
|
||
// solhint-disable-next-line func-name-mixedcase | ||
function CLOCK_MODE() public view virtual override returns (string memory) { | ||
return "mode=timestamp"; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.2; | ||
|
||
import "../patched/governance/Governor.sol"; | ||
import "../patched/governance/extensions/GovernorCountingSimple.sol"; | ||
import "../patched/governance/extensions/GovernorTimelockControl.sol"; | ||
import "../patched/governance/extensions/GovernorVotes.sol"; | ||
import "../patched/governance/extensions/GovernorVotesQuorumFraction.sol"; | ||
import "../patched/token/ERC20/extensions/ERC20Votes.sol"; | ||
|
||
contract GovernorHarness is | ||
Governor, | ||
GovernorCountingSimple, | ||
GovernorTimelockControl, | ||
GovernorVotes, | ||
GovernorVotesQuorumFraction | ||
{ | ||
constructor(IVotes _token, TimelockController _timelock, uint256 _quorumNumeratorValue) | ||
Governor("Harness") | ||
GovernorTimelockControl(_timelock) | ||
GovernorVotes(_token) | ||
GovernorVotesQuorumFraction(_quorumNumeratorValue) | ||
{} | ||
|
||
// Harness from Votes | ||
function token_getPastTotalSupply(uint256 blockNumber) public view returns(uint256) { | ||
return token.getPastTotalSupply(blockNumber); | ||
} | ||
|
||
function token_getPastVotes(address account, uint256 blockNumber) public view returns(uint256) { | ||
return token.getPastVotes(account, blockNumber); | ||
} | ||
|
||
function token_clock() public view returns (uint48) { | ||
return token.clock(); | ||
} | ||
|
||
function token_CLOCK_MODE() public view returns (string memory) { | ||
return token.CLOCK_MODE(); | ||
} | ||
|
||
// Harness from Governor | ||
function getExecutor() public view returns (address) { | ||
return _executor(); | ||
} | ||
|
||
function proposalProposer(uint256 proposalId) public view returns (address) { | ||
return _proposalProposer(proposalId); | ||
} | ||
|
||
function quorumReached(uint256 proposalId) public view returns (bool) { | ||
return _quorumReached(proposalId); | ||
} | ||
|
||
function voteSucceeded(uint256 proposalId) public view returns (bool) { | ||
return _voteSucceeded(proposalId); | ||
} | ||
|
||
function isExecuted(uint256 proposalId) public view returns (bool) { | ||
return _isExecuted(proposalId); | ||
} | ||
|
||
function isCanceled(uint256 proposalId) public view returns (bool) { | ||
return _isCanceled(proposalId); | ||
} | ||
|
||
// Harness from GovernorCountingSimple | ||
function getAgainstVotes(uint256 proposalId) public view returns (uint256) { | ||
(uint256 againstVotes,,) = proposalVotes(proposalId); | ||
return againstVotes; | ||
} | ||
|
||
function getForVotes(uint256 proposalId) public view returns (uint256) { | ||
(,uint256 forVotes,) = proposalVotes(proposalId); | ||
return forVotes; | ||
} | ||
|
||
function getAbstainVotes(uint256 proposalId) public view returns (uint256) { | ||
(,,uint256 abstainVotes) = proposalVotes(proposalId); | ||
return abstainVotes; | ||
} | ||
|
||
/// The following functions are overrides required by Solidity added by Certora. | ||
// mapping(uint256 => uint256) public ghost_sum_vote_power_by_id; | ||
// | ||
// function _castVote( | ||
// uint256 proposalId, | ||
// address account, | ||
// uint8 support, | ||
// string memory reason, | ||
// bytes memory params | ||
// ) internal virtual override returns (uint256) { | ||
// uint256 deltaWeight = super._castVote(proposalId, account, support, reason, params); | ||
// ghost_sum_vote_power_by_id[proposalId] += deltaWeight; | ||
// return deltaWeight; | ||
// } | ||
|
||
// The following functions are overrides required by Solidity added by OZ Wizard. | ||
function votingDelay() public pure override returns (uint256) { | ||
return 1; // 1 block | ||
} | ||
|
||
function votingPeriod() public pure override returns (uint256) { | ||
return 45818; // 1 week | ||
} | ||
|
||
function quorum(uint256 blockNumber) | ||
public | ||
view | ||
override(IGovernor, GovernorVotesQuorumFraction) | ||
returns (uint256) | ||
{ | ||
return super.quorum(blockNumber); | ||
} | ||
|
||
function state(uint256 proposalId) public view override(Governor, GovernorTimelockControl) returns (ProposalState) { | ||
return super.state(proposalId); | ||
} | ||
|
||
function propose( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
string memory description | ||
) public override(Governor, IGovernor) returns (uint256) { | ||
return super.propose(targets, values, calldatas, description); | ||
} | ||
|
||
function _execute( | ||
uint256 proposalId, | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
bytes32 descriptionHash | ||
) internal override(Governor, GovernorTimelockControl) { | ||
super._execute(proposalId, targets, values, calldatas, descriptionHash); | ||
} | ||
|
||
function _cancel( | ||
address[] memory targets, | ||
uint256[] memory values, | ||
bytes[] memory calldatas, | ||
bytes32 descriptionHash | ||
) internal override(Governor, GovernorTimelockControl) returns (uint256) { | ||
return super._cancel(targets, values, calldatas, descriptionHash); | ||
} | ||
|
||
function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) { | ||
return super._executor(); | ||
} | ||
|
||
function supportsInterface(bytes4 interfaceId) | ||
public | ||
view | ||
override(Governor, GovernorTimelockControl) | ||
returns (bool) | ||
{ | ||
return super.supportsInterface(interfaceId); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "../patched/access/Ownable2Step.sol"; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "../patched/access/Ownable.sol"; | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const product = (...arrays) => arrays.reduce((a, b) => a.flatMap(ai => b.map(bi => [ai, bi].flat()))); | ||
frangio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
module.exports = [ | ||
{ | ||
spec: 'AccessControl', | ||
contract: 'AccessControlHarness', | ||
files: ['certora/harnesses/AccessControlHarness.sol'], | ||
}, | ||
{ | ||
spec: 'Ownable', | ||
contract: 'OwnableHarness', | ||
files: ['certora/harnesses/OwnableHarness.sol'], | ||
}, | ||
{ | ||
spec: 'Ownable2Step', | ||
contract: 'Ownable2StepHarness', | ||
files: ['certora/harnesses/Ownable2StepHarness.sol'], | ||
}, | ||
{ | ||
spec: 'ERC20', | ||
contract: 'ERC20PermitHarness', | ||
files: ['certora/harnesses/ERC20PermitHarness.sol'], | ||
options: ['--optimistic_loop'], | ||
}, | ||
{ | ||
spec: 'ERC20FlashMint', | ||
contract: 'ERC20FlashMintHarness', | ||
files: ['certora/harnesses/ERC20FlashMintHarness.sol', 'certora/harnesses/ERC3156FlashBorrowerHarness.sol'], | ||
options: ['--optimistic_loop'], | ||
}, | ||
{ | ||
spec: 'ERC20Wrapper', | ||
contract: 'ERC20WrapperHarness', | ||
files: ['certora/harnesses/ERC20PermitHarness.sol', 'certora/harnesses/ERC20WrapperHarness.sol'], | ||
options: ['--link ERC20WrapperHarness:_underlying=ERC20PermitHarness', '--optimistic_loop'], | ||
}, | ||
{ | ||
spec: 'Initializable', | ||
contract: 'InitializableHarness', | ||
files: ['certora/harnesses/InitializableHarness.sol'], | ||
}, | ||
...product( | ||
['GovernorBase', 'GovernorInvariants', 'GovernorStates', 'GovernorFunctions'], | ||
['ERC20VotesBlocknumberHarness', 'ERC20VotesTimestampHarness'], | ||
).map(([spec, token]) => ({ | ||
spec, | ||
contract: 'GovernorHarness', | ||
files: ['certora/harnesses/GovernorHarness.sol', `certora/harnesses/${token}.sol`], | ||
options: [`--link GovernorHarness:token=${token}`, '--optimistic_loop', '--optimistic_hashing'], | ||
})), | ||
]; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.