GovernorInvariants.spec 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import "helpers.spec"
  2. import "Governor.helpers.spec"
  3. /*
  4. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  5. │ Invariant: clock is consistent between the goernor and the token │
  6. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  7. */
  8. rule clockMode(env e) {
  9. require clockSanity(e);
  10. assert clock(e) == e.block.number || clock(e) == e.block.timestamp;
  11. assert clock(e) == token_clock(e);
  12. /// This causes a failure in the prover
  13. // assert CLOCK_MODE(e) == token_CLOCK_MODE(e);
  14. }
  15. /*
  16. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  17. │ Invariant: Votes start and end are either initialized (non zero) or uninitialized (zero) simultaneously │
  18. │ │
  19. │ This invariant assumes that the block number cannot be 0 at any stage of the contract cycle │
  20. │ This is very safe assumption as usually the 0 block is genesis block which is uploaded with data │
  21. │ by the developers and will not be valid to raise proposals (at the current way that block chain is functioning) │
  22. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  23. */
  24. invariant proposalStateConsistency(uint256 pId)
  25. (proposalProposer(pId) == 0 <=> proposalSnapshot(pId) == 0) &&
  26. (proposalProposer(pId) == 0 <=> proposalDeadline(pId) == 0)
  27. {
  28. preserved with (env e) {
  29. require clockSanity(e);
  30. }
  31. }
  32. /*
  33. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  34. │ Invariant: votes recorded => created │
  35. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  36. */
  37. invariant votesImplyCreated(uint256 pId)
  38. (
  39. getAgainstVotes(pId) > 0 ||
  40. getForVotes(pId) > 0 ||
  41. getAbstainVotes(pId) > 0
  42. ) => proposalCreated(pId)
  43. {
  44. preserved with (env e) {
  45. require clockSanity(e);
  46. requireInvariant proposalStateConsistency(pId);
  47. }
  48. }
  49. /*
  50. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  51. │ Invariant: cancel => created │
  52. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  53. */
  54. invariant canceledImplyCreated(uint pId)
  55. isCanceled(pId) => proposalCreated(pId)
  56. {
  57. preserved with (env e) {
  58. require clockSanity(e);
  59. requireInvariant proposalStateConsistency(pId);
  60. }
  61. }
  62. /*
  63. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  64. │ Invariant: executed => created │
  65. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  66. */
  67. invariant executedImplyCreated(uint pId)
  68. isExecuted(pId) => proposalCreated(pId)
  69. {
  70. preserved with (env e) {
  71. require clockSanity(e);
  72. requireInvariant proposalStateConsistency(pId);
  73. }
  74. }
  75. /*
  76. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  77. │ Invariant: queued => created │
  78. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  79. */
  80. invariant queuedImplyCreated(uint pId)
  81. isQueued(pId) => proposalCreated(pId)
  82. {
  83. preserved with (env e) {
  84. require clockSanity(e);
  85. requireInvariant proposalStateConsistency(pId);
  86. }
  87. }
  88. /*
  89. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  90. │ Invariant: timmings │
  91. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  92. */
  93. invariant votesImplySnapshotPassed(env e, uint256 pId)
  94. (
  95. getAgainstVotes(pId) > 0 ||
  96. getForVotes(pId) > 0 ||
  97. getAbstainVotes(pId) > 0
  98. ) => proposalSnapshot(pId) < clock(e)
  99. {
  100. preserved with (env e2) {
  101. require clock(e) == clock(e2);
  102. }
  103. }
  104. invariant queuedImplyDeadlineOver(env e, uint pId)
  105. isQueued(pId) => proposalDeadline(pId) < clock(e)
  106. {
  107. preserved {
  108. require clockSanity(e);
  109. requireInvariant proposalStateConsistency(pId);
  110. }
  111. }
  112. /*
  113. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  114. │ Invariant: Votes start before it ends │
  115. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  116. */
  117. invariant voteStartBeforeVoteEnd(uint256 pId)
  118. proposalSnapshot(pId) <= proposalDeadline(pId)
  119. {
  120. preserved {
  121. requireInvariant proposalStateConsistency(pId);
  122. }
  123. }
  124. /*
  125. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  126. │ Invariant: A proposal cannot be both executed and canceled simultaneously │
  127. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  128. */
  129. invariant noBothExecutedAndCanceled(uint256 pId)
  130. !isExecuted(pId) || !isCanceled(pId)
  131. /*
  132. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  133. │ Invariant: the "governance call" dequeue is empty │
  134. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  135. */
  136. invariant governanceCallLength()
  137. governanceCallLength() == 0