GovernorInvariants.spec 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import "helpers.spec"
  2. import "methods/IGovernor.spec"
  3. import "Governor.helpers.spec"
  4. /*
  5. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  6. │ Invariant: clock is consistent between the goernor and the token │
  7. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  8. */
  9. rule clockMode(env e) {
  10. require e.block.number < max_uint48() && e.block.timestamp < max_uint48();
  11. assert clock(e) == e.block.number || clock(e) == e.block.timestamp;
  12. assert clock(e) == token_clock(e);
  13. /// This causes a failure in the prover
  14. // assert CLOCK_MODE(e) == token_CLOCK_MODE(e);
  15. }
  16. /*
  17. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  18. │ Invariant: Votes start and end are either initialized (non zero) or uninitialized (zero) simultaneously │
  19. │ │
  20. │ This invariant assumes that the block number cannot be 0 at any stage of the contract cycle │
  21. │ This is very safe assumption as usually the 0 block is genesis block which is uploaded with data │
  22. │ by the developers and will not be valid to raise proposals (at the current way that block chain is functioning) │
  23. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  24. */
  25. invariant proposalStateConsistency(uint256 pId)
  26. (proposalProposer(pId) == 0 <=> proposalSnapshot(pId) == 0) &&
  27. (proposalProposer(pId) == 0 <=> proposalDeadline(pId) == 0)
  28. {
  29. preserved with (env e) {
  30. require clock(e) > 0;
  31. }
  32. }
  33. /*
  34. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  35. │ Invariant: cancel => created │
  36. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  37. */
  38. invariant canceledImplyCreated(uint pId)
  39. isCanceled(pId) => proposalCreated(pId)
  40. {
  41. preserved with (env e) {
  42. requireInvariant proposalStateConsistency(pId);
  43. require clock(e) > 0;
  44. }
  45. }
  46. /*
  47. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  48. │ Invariant: executed => created │
  49. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  50. */
  51. invariant executedImplyCreated(uint pId)
  52. isExecuted(pId) => proposalCreated(pId)
  53. {
  54. preserved with (env e) {
  55. requireInvariant proposalStateConsistency(pId);
  56. require clock(e) > 0;
  57. }
  58. }
  59. /*
  60. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  61. │ Invariant: The state UNSET() correctly catched uninitialized proposal. │
  62. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  63. */
  64. invariant proposalStateConsistencyUnset(env e, uint256 pId)
  65. proposalCreated(pId) <=> safeState(e, pId) == UNSET()
  66. {
  67. preserved {
  68. require clock(e) > 0;
  69. }
  70. }
  71. /*
  72. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  73. │ Invariant: Votes start before it ends │
  74. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  75. */
  76. invariant voteStartBeforeVoteEnd(uint256 pId)
  77. proposalSnapshot(pId) <= proposalDeadline(pId)
  78. {
  79. preserved {
  80. requireInvariant proposalStateConsistency(pId);
  81. }
  82. }
  83. /*
  84. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  85. │ Invariant: A proposal cannot be both executed and canceled simultaneously │
  86. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  87. */
  88. invariant noBothExecutedAndCanceled(uint256 pId)
  89. !isExecuted(pId) || !isCanceled(pId)
  90. /*
  91. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  92. │ Invariant: the "governance call" dequeue is empty │
  93. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  94. */
  95. invariant governanceCallLength()
  96. governanceCallLength() == 0