GovernorPreventLateQuorum.spec 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import "helpers.spec"
  2. import "methods/IGovernor.spec"
  3. import "Governor.helpers.spec"
  4. import "GovernorInvariants.spec"
  5. methods {
  6. lateQuorumVoteExtension() returns uint64 envfree
  7. getExtendedDeadline(uint256) returns uint64 envfree
  8. }
  9. use invariant proposalStateConsistency
  10. use invariant votesImplySnapshotPassed
  11. /*
  12. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  13. โ”‚ Rule: โ”‚
  14. โ”‚ * Deadline can never be reduced โ”‚
  15. โ”‚ * If deadline increases then we are in `deadlineExtended` state and `castVote` was called. โ”‚
  16. โ”‚ * A proposal's deadline can't change in `deadlineExtended` state. โ”‚
  17. โ”‚ * A proposal's deadline can't be unextended. โ”‚
  18. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  19. */
  20. rule deadlineChangeToPreventLateQuorum(uint256 pId, env e, method f, calldataarg args)
  21. filtered { f -> !skip(f) }
  22. {
  23. require clockSanity(e);
  24. requireInvariant proposalStateConsistency(pId);
  25. requireInvariant votesImplySnapshotPassed(e, pId);
  26. // This is not (easily) provable as an invariant because the prover think `_totalSupplyCheckpoints`
  27. // can arbitrarily change, which causes the quorum() to change. Not sure how to fix that.
  28. require quorumReached(pId) <=> getExtendedDeadline(pId) > 0;
  29. uint256 deadlineBefore = proposalDeadline(pId);
  30. bool deadlineExtendedBefore = getExtendedDeadline(pId) > 0;
  31. bool quorumReachedBefore = quorumReached(pId);
  32. f(e, args);
  33. uint256 deadlineAfter = proposalDeadline(pId);
  34. bool deadlineExtendedAfter = getExtendedDeadline(pId) > 0;
  35. bool quorumReachedAfter = quorumReached(pId);
  36. // deadline can never be reduced
  37. assert deadlineBefore <= proposalDeadline(pId);
  38. // deadline can only be extended in proposal or on cast vote
  39. assert deadlineAfter != deadlineBefore => (
  40. (
  41. !deadlineExtendedBefore &&
  42. !deadlineExtendedAfter &&
  43. f.selector == propose(address[], uint256[], bytes[], string).selector
  44. ) || (
  45. !deadlineExtendedBefore &&
  46. deadlineExtendedAfter &&
  47. !quorumReachedBefore &&
  48. quorumReachedAfter &&
  49. deadlineAfter == clock(e) + lateQuorumVoteExtension() &&
  50. votingAll(f)
  51. )
  52. );
  53. // a deadline can only be extended once
  54. assert deadlineExtendedBefore => deadlineBefore == deadlineAfter;
  55. // a deadline cannot be un-extended
  56. assert deadlineExtendedBefore => deadlineExtendedAfter;
  57. }