checkingInvariantsWithoutGhosts

pull/2997/head
Aleksander Kryukov 3 years ago
parent bfa1dd3756
commit f08ee568b9
  1. 8
      certora/harnesses/GovernorHarness.sol
  2. 3
      certora/scripts/Governor.sh
  3. 22
      certora/specs/GovernorBase.spec
  4. 2
      contracts/governance/Governor.sol

@ -2,6 +2,14 @@ import "../../contracts/governance/Governor.sol";
contract GovernorHarness is Governor {
function isExecuted(uint256 proposalId) public view returns (bool) {
return _proposals[proposalId].executed;
}
function isCanceled(uint256 proposalId) public view returns (bool) {
return _proposals[proposalId].canceled;
}
mapping(uint256 => uint256) _quorum;
function quorum(uint256 blockNumber) public view override virtual returns (uint256) {

@ -3,7 +3,6 @@ certoraRun certora/harnesses/GovernorHarness.sol \
--solc solc8.0 \
--staging \
--optimistic_loop \
--disableLocalTypeChecking \
--settings -copyLoopUnroll=4 \
--rule voteStartBeforeVoteEnd \
--rule noExecuteOrCancelBeforeStarting \
--msg "$1"

@ -2,25 +2,32 @@
methods {
proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
hashProposal(address[],uint256[],bytes[],bytes32) returns uint256 envfree
isExecuted(uint256) returns bool envfree
isCanceled(uint256) returns bool envfree
// internal functions made public in harness:
_quorumReached(uint256) returns bool envfree
_voteSucceeded(uint256) returns bool envfree
}
/*
ghost proposalVoteStart(uint256) returns uint64 {
init_state axiom forall uint256 pId. proposalVoteStart(pId) == 0;
}
ghost proposalVoteEnd(uint256) returns uint64 {
init_state axiom forall uint256 pId. proposalVoteEnd(pId) == 0;
}
*/
/*
ghost proposalExecuted(uint256) returns bool {
init_state axiom forall uint256 pId. !proposalExecuted(pId);
}
ghost proposalCanceled(uint256) returns bool {
init_state axiom forall uint256 pId. !proposalCanceled(pId);
}
*/
/*
hook Sstore _proposals[KEY uint256 pId].voteStart._deadline uint64 newValue STORAGE {
havoc proposalVoteStart assuming (
proposalVoteStart@new(pId) == newValue
@ -42,21 +49,22 @@ hook Sstore _proposals[KEY uint256 pId].voteEnd._deadline uint64 newValue STORAG
hook Sload uint64 value _proposals[KEY uint256 pId].voteEnd._deadline STORAGE {
require proposalVoteEnd(pId) == value;
}
*/
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// SANITY CHECKS ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
/*
rule sanityCheckVoteStart(method f, uint256 pId) {
uint64 preGhost = proposalVoteStart(pId);
uint64 preGhost = _proposals(pId).voteStart._deadline;
uint256 pre = proposalSnapshot(pId);
env e;
calldataarg arg;
f(e, arg);
uint64 postGhost = proposalVoteStart(pId);
uint64 postGhost = _proposals(pId).voteStart._deadline;
uint256 post = proposalSnapshot(pId);
assert preGhost == postGhost <=> pre == post, "ghost changes are correlated with getter changes";
@ -77,7 +85,7 @@ rule sanityCheckVoteEnd(method f, uint256 pId) {
assert preGhost == postGhost <=> pre == post, "ghost changes are correlated with getter changes";
assert pre == preGhost => post == postGhost, "if correlated at the beginning should be correlated at the end";
}
*/
//////////////////////////////////////////////////////////////////////////////
////////////////////////////// INVARIANTS ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@ -91,12 +99,12 @@ invariant voteStartBeforeVoteEnd(uint256 pId) proposalVoteStart(pId) < proposalV
/**
* A proposal cannot be both executed and canceled.
*/
invariant noBothExecutedAndCanceled(uint256 pId) !proposalExecuted(pId) || !proposalCanceled(pId)
invariant noBothExecutedAndCanceled(uint256 pId) !isExecuted(pId) || !isCanceled(pId)
/**
* A proposal cannot be executed nor canceled before it starts
*/
invariant noExecuteOrCancelBeforeStarting(env e, uint256 pId) e.block.timestamp < proposalVoteStart(pId) => !proposalExecuted(pId) && !proposalCanceled(pId)
invariant noExecuteOrCancelBeforeStarting(env e, uint256 pId) e.block.timestamp < proposalVoteStart(pId) => !isExecuted(pId) && !isCanceled(pId)
/**
* The voting must start not before the proposal’s creation time

@ -37,7 +37,7 @@ abstract contract Governor is Context, ERC165, EIP712, IGovernor {
string private _name;
mapping(uint256 => ProposalCore) private _proposals;
mapping(uint256 => ProposalCore) public _proposals;
/**
* @dev Restrict access to governor executing address. Some module might override the _executor function to make

Loading…
Cancel
Save