GovernorInvariants.spec 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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 => proposal snapshot is in the past │
  35. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  36. */
  37. invariant votesImplySnapshotPassed(env e, uint256 pId)
  38. (getAgainstVotes(pId) > 0 => proposalSnapshot(pId) <= clock(e)) &&
  39. (getForVotes(pId) > 0 => proposalSnapshot(pId) <= clock(e)) &&
  40. (getAbstainVotes(pId) > 0 => proposalSnapshot(pId) <= clock(e))
  41. {
  42. preserved {
  43. require clockSanity(e);
  44. }
  45. }
  46. /*
  47. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  48. │ Invariant: cancel => created │
  49. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  50. */
  51. invariant canceledImplyCreated(uint pId)
  52. isCanceled(pId) => proposalCreated(pId)
  53. {
  54. preserved with (env e) {
  55. require clockSanity(e);
  56. requireInvariant proposalStateConsistency(pId);
  57. }
  58. }
  59. /*
  60. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  61. │ Invariant: executed => created │
  62. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  63. */
  64. invariant executedImplyCreated(uint pId)
  65. isExecuted(pId) => proposalCreated(pId)
  66. {
  67. preserved with (env e) {
  68. require clockSanity(e);
  69. requireInvariant proposalStateConsistency(pId);
  70. }
  71. }
  72. /*
  73. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  74. │ Invariant: queued => created │
  75. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  76. */
  77. invariant queuedImplyCreated(uint pId)
  78. isQueued(pId) => proposalCreated(pId)
  79. {
  80. preserved with (env e) {
  81. require clockSanity(e);
  82. requireInvariant proposalStateConsistency(pId);
  83. }
  84. }
  85. invariant queuedImplyVoteOverAndSuccessful(env e, uint pId)
  86. isQueued(pId) => (
  87. quorumReached(pId) &&
  88. voteSucceeded(pId) &&
  89. proposalDeadline(pId) < clock(e)
  90. )
  91. {
  92. preserved {
  93. require clockSanity(e);
  94. requireInvariant proposalStateConsistency(pId);
  95. }
  96. }
  97. /*
  98. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  99. │ Invariant: Votes start before it ends │
  100. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  101. */
  102. invariant voteStartBeforeVoteEnd(uint256 pId)
  103. proposalSnapshot(pId) <= proposalDeadline(pId)
  104. {
  105. preserved {
  106. requireInvariant proposalStateConsistency(pId);
  107. }
  108. }
  109. /*
  110. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  111. │ Invariant: A proposal cannot be both executed and canceled simultaneously │
  112. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  113. */
  114. invariant noBothExecutedAndCanceled(uint256 pId)
  115. !isExecuted(pId) || !isCanceled(pId)
  116. /*
  117. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  118. │ Invariant: the "governance call" dequeue is empty │
  119. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  120. */
  121. invariant governanceCallLength()
  122. governanceCallLength() == 0