CountingSimpleMoreCleanAndAddedMoreRules

This commit is contained in:
Aleksander Kryukov
2021-11-11 17:28:22 +02:00
parent 0d724ca892
commit 0598a3ac43
2 changed files with 151 additions and 133 deletions

View File

@ -1,6 +1,7 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
///////////////////// Governor.sol base definitions ////////////////////////// ///////////////////// Governor.sol base definitions //////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
methods { methods {
proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
proposalDeadline(uint256) returns uint256 envfree proposalDeadline(uint256) returns uint256 envfree
@ -17,8 +18,8 @@ methods {
// internal functions made public in harness: // internal functions made public in harness:
_quorumReached(uint256) returns bool envfree _quorumReached(uint256) returns bool envfree
_voteSucceeded(uint256) returns bool envfree _voteSucceeded(uint256) returns bool envfree
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////// INVARIANTS //////////////////////////////////// ////////////////////////////// INVARIANTS ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -32,22 +33,14 @@ methods {
&& (proposalSnapshot(pId) == 0 => proposalDeadline(pId) == 0) && (proposalSnapshot(pId) == 0 => proposalDeadline(pId) == 0)
/* /**
* A proposal cannot be both executed and canceled. * A proposal cannot be both executed and canceled.
*/ */
invariant noBothExecutedAndCanceled(uint256 pId) invariant noBothExecutedAndCanceled(uint256 pId)
!isExecuted(pId) || !isCanceled(pId) !isExecuted(pId) || !isCanceled(pId)
/* /**
* A proposal cannot be neither executed nor canceled before it starts
*/
invariant noExecuteOrCancelBeforeStarting(env e, uint256 pId)
e.block.number < proposalSnapshot(pId)
=> !isExecuted(pId) && !isCanceled(pId)
/*
* A proposal could be executed only if quorum was reached and vote succeeded * A proposal could be executed only if quorum was reached and vote succeeded
*/ */
invariant executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId) invariant executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId)
@ -58,6 +51,29 @@ methods {
/////////////////////////////////// RULES //////////////////////////////////// /////////////////////////////////// RULES ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/*
* No functions should be allowed to run after a job is deemed as canceled
*/
rule cannotSetIfCanceled(uint256 pId, method f) filtered { f-> !f.isView }{
require(isCanceled(pId));
env e; calldataarg args;
f(e, args);
assert(isCanceled(pId) => lastReverted == true, "Function did not revert when canceled");
}
/*
* No functions should be allowed to run after a job is deemed as executed
*/
rule cannotSetIfExecuted(uint256 pId, method f) filtered { f-> !f.isView }{
require(isExecuted(pId));
env e; calldataarg args;
f(e, args);
assert(isExecuted(pId) => lastReverted == true, "Function did not revert after executed");
}
/* /*
* The voting must start not before the proposals creation time * The voting must start not before the proposals creation time
*/ */
@ -101,7 +117,6 @@ methods {
address user = e.msg.sender; address user = e.msg.sender;
bool votedCheck = hasVoted(e, pId, user); bool votedCheck = hasVoted(e, pId, user);
require votedCheck == true;
castVote@withrevert(e, pId, sup); castVote@withrevert(e, pId, sup);
bool reverted = lastReverted; bool reverted = lastReverted;
@ -145,3 +160,33 @@ methods {
assert equalHashes => d1 == d2; assert equalHashes => d1 == d2;
} }
*/ */
/**
* A proposal cannot be neither executed nor canceled before it starts
*/
rule noExecuteOrCancelBeforeStarting(uint256 pId, method f){
env e;
require !isExecuted(pId) && !isCanceled(pId);
calldataarg arg;
f(e, arg);
assert e.block.number < proposalSnapshot(pId) => (!isExecuted(pId) && !isCanceled(pId)), "executed/cancelled before start";
}
/**
* A proposal cannot be neither executed nor canceled before proposal's deadline
*/
rule noExecuteOrCancelBeforeDeadline(uint256 pId, method f){
env e;
requireInvariant voteStartBeforeVoteEnd(pId);
require !isExecuted(pId) && !isCanceled(pId);
calldataarg arg;
f(e, arg);
assert e.block.number < proposalDeadline(pId) => (!isExecuted(pId) && !isCanceled(pId)), "executed/cancelled before start";
}

View File

@ -1,23 +1,6 @@
////////////////////////////////////////////////////////////////////////////// import "GovernorBase.spec"
///////////////////// Governor.sol base definitions //////////////////////////
//////////////////////////////////////////////////////////////////////////////
methods { methods {
proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
proposalDeadline(uint256) returns uint256 envfree
hashProposal(address[],uint256[],bytes[],bytes32) returns uint256 envfree
isExecuted(uint256) returns bool envfree
isCanceled(uint256) returns bool envfree
// initialized(uint256) returns bool envfree
hasVoted(uint256, address) returns bool
castVote(uint256, uint8) returns uint256
// internal functions made public in harness:
_quorumReached(uint256) returns bool envfree
_voteSucceeded(uint256) returns bool envfree
// getter for checking the sums
ghost_sum_vote_power_by_id(uint256) returns uint256 envfree ghost_sum_vote_power_by_id(uint256) returns uint256 envfree
} }
@ -40,29 +23,19 @@ ghost sum_tracked_weight() returns uint256 {
init_state axiom sum_tracked_weight() == 0; init_state axiom sum_tracked_weight() == 0;
} }
/*
function update_tracked_weights(uint256 pId, uint256 votes, uint256 old_votes) {
havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
(p != pId => tracked_weight@new(p) == tracked_weight@old(p));
havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
}*/
hook Sstore _proposalVotes[KEY uint256 pId].againstVotes uint256 votes (uint256 old_votes) STORAGE { hook Sstore _proposalVotes[KEY uint256 pId].againstVotes uint256 votes (uint256 old_votes) STORAGE {
//update_tracked_weights(pId, votes, old_votes);
havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) && havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
(p != pId => tracked_weight@new(p) == tracked_weight@old(p)); (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes; havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
} }
hook Sstore _proposalVotes[KEY uint256 pId].forVotes uint256 votes (uint256 old_votes) STORAGE { hook Sstore _proposalVotes[KEY uint256 pId].forVotes uint256 votes (uint256 old_votes) STORAGE {
//update_tracked_weights(pId, votes, old_votes);
havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) && havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
(p != pId => tracked_weight@new(p) == tracked_weight@old(p)); (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes; havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;
} }
hook Sstore _proposalVotes[KEY uint256 pId].abstainVotes uint256 votes (uint256 old_votes) STORAGE { hook Sstore _proposalVotes[KEY uint256 pId].abstainVotes uint256 votes (uint256 old_votes) STORAGE {
//update_tracked_weights(pId, votes, old_votes);
havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) && havoc tracked_weight assuming forall uint256 p. (p == pId => tracked_weight@new(p) == tracked_weight@old(p) - old_votes + votes) &&
(p != pId => tracked_weight@new(p) == tracked_weight@old(p)); (p != pId => tracked_weight@new(p) == tracked_weight@old(p));
havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes; havoc sum_tracked_weight assuming sum_tracked_weight@new() == sum_tracked_weight@old() - old_votes + votes;