|
@@ -17,10 +17,6 @@ definition assumedSafeOrDuplicate(method f) returns bool =
|
|
|
│ Rule: state returns one of the value in the enumeration │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
|
*/
|
|
|
-invariant stateConsistency(env e, uint256 pId)
|
|
|
- state(e, pId) == safeState(e, pId)
|
|
|
- filtered { f -> !assumedSafeOrDuplicate(f) }
|
|
|
-
|
|
|
rule stateDomain(env e, uint256 pId) {
|
|
|
uint8 result = safeState(e, pId);
|
|
|
assert (
|
|
@@ -37,7 +33,7 @@ rule stateDomain(env e, uint256 pId) {
|
|
|
|
|
|
/*
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
|
-│ Rule: State transitions caused by function calls │
|
|
|
+│ [DISABLED] Rule: State transitions caused by function calls │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
|
*/
|
|
|
/// Previous version that results in the prover timing out.
|
|
@@ -60,61 +56,62 @@ rule stateDomain(env e, uint256 pId) {
|
|
|
// );
|
|
|
// }
|
|
|
|
|
|
-function stateTransitionFnHelper(method f, uint8 s) returns uint8 {
|
|
|
- uint256 pId; env e; calldataarg args;
|
|
|
-
|
|
|
- require clockSanity(e);
|
|
|
- require quorumNumeratorLength() < max_uint256; // sanity
|
|
|
-
|
|
|
- require safeState(e, pId) == s; // constrain state before
|
|
|
- f(e, args);
|
|
|
- require safeState(e, pId) != s; // constrain state after
|
|
|
-
|
|
|
- return safeState(e, pId);
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_UNSET(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, UNSET());
|
|
|
- assert stateAfter == PENDING() && f.selector == propose(address[],uint256[],bytes[],string).selector;
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_PENDING(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, PENDING());
|
|
|
- assert stateAfter == CANCELED() && f.selector == cancel(address[],uint256[],bytes[],bytes32).selector;
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_ACTIVE(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, ACTIVE());
|
|
|
- assert false;
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_CANCELED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, CANCELED());
|
|
|
- assert false;
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_DEFEATED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, DEFEATED());
|
|
|
- assert false;
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_SUCCEEDED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, SUCCEEDED());
|
|
|
- assert (
|
|
|
- (stateAfter == QUEUED() && f.selector == queue(address[],uint256[],bytes[],bytes32).selector) ||
|
|
|
- (stateAfter == EXECUTED() && f.selector == execute(address[],uint256[],bytes[],bytes32).selector)
|
|
|
- );
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_QUEUED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, QUEUED());
|
|
|
- assert stateAfter == EXECUTED() && f.selector == execute(address[],uint256[],bytes[],bytes32).selector;
|
|
|
-}
|
|
|
-
|
|
|
-rule stateTransitionFn_EXECUTED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
- uint8 stateAfter = stateTransitionFnHelper(f, EXECUTED());
|
|
|
- assert false;
|
|
|
-}
|
|
|
+/// This version also causes a lot of timeouts so we comment it out of now
|
|
|
+// function stateTransitionFnHelper(method f, uint8 s) returns uint8 {
|
|
|
+// uint256 pId; env e; calldataarg args;
|
|
|
+//
|
|
|
+// require clockSanity(e);
|
|
|
+// require quorumNumeratorLength() < max_uint256; // sanity
|
|
|
+//
|
|
|
+// require safeState(e, pId) == s; // constrain state before
|
|
|
+// f(e, args);
|
|
|
+// require safeState(e, pId) != s; // constrain state after
|
|
|
+//
|
|
|
+// return safeState(e, pId);
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_UNSET(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, UNSET());
|
|
|
+// assert stateAfter == PENDING() && f.selector == propose(address[],uint256[],bytes[],string).selector;
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_PENDING(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, PENDING());
|
|
|
+// assert stateAfter == CANCELED() && f.selector == cancel(address[],uint256[],bytes[],bytes32).selector;
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_ACTIVE(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, ACTIVE());
|
|
|
+// assert false;
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_CANCELED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, CANCELED());
|
|
|
+// assert false;
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_DEFEATED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, DEFEATED());
|
|
|
+// assert false;
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_SUCCEEDED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, SUCCEEDED());
|
|
|
+// assert (
|
|
|
+// (stateAfter == QUEUED() && f.selector == queue(address[],uint256[],bytes[],bytes32).selector) ||
|
|
|
+// (stateAfter == EXECUTED() && f.selector == execute(address[],uint256[],bytes[],bytes32).selector)
|
|
|
+// );
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_QUEUED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, QUEUED());
|
|
|
+// assert stateAfter == EXECUTED() && f.selector == execute(address[],uint256[],bytes[],bytes32).selector;
|
|
|
+// }
|
|
|
+//
|
|
|
+// rule stateTransitionFn_EXECUTED(method f) filtered { f -> !assumedSafeOrDuplicate(f) } {
|
|
|
+// uint8 stateAfter = stateTransitionFnHelper(f, EXECUTED());
|
|
|
+// assert false;
|
|
|
+// }
|
|
|
|
|
|
/*
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
@@ -122,9 +119,9 @@ rule stateTransitionFn_EXECUTED(method f) filtered { f -> !assumedSafeOrDuplicat
|
|
|
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
|
*/
|
|
|
// The timelockId can be set in states QUEUED, EXECUTED and CANCELED. However, checking the full scope of this results
|
|
|
-// in a timeout. This is a weaker version that is still useful
|
|
|
+// in a timeout. This is a weaker version that is still useful. Ideally we would check `safeState`.
|
|
|
invariant noTimelockBeforeEndOfVote(env e, uint256 pId)
|
|
|
- safeState(e, pId) == ACTIVE() => timelockId(pId) == 0
|
|
|
+ state(e, pId) == ACTIVE() => timelockId(pId) == 0
|
|
|
|
|
|
rule stateTransitionWait(uint256 pId, env e1, env e2) {
|
|
|
require clockSanity(e1);
|
|
@@ -137,8 +134,8 @@ rule stateTransitionWait(uint256 pId, env e1, env e2) {
|
|
|
requireInvariant votesImplySnapshotPassed(e1, pId);
|
|
|
requireInvariant noTimelockBeforeEndOfVote(e1, pId);
|
|
|
|
|
|
- uint8 stateBefore = safeState(e1, pId);
|
|
|
- uint8 stateAfter = safeState(e2, pId);
|
|
|
+ uint8 stateBefore = state(e1, pId); // Ideally we would use "safeState(e1, pId)"
|
|
|
+ uint8 stateAfter = state(e2, pId); // Ideally we would use "safeState(e2, pId)"
|
|
|
|
|
|
assert (stateBefore != stateAfter) => (
|
|
|
(stateBefore == PENDING() && stateAfter == ACTIVE() ) ||
|