GovernorFunctions.spec 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import "helpers.spec"
  2. import "methods/IGovernor.spec"
  3. import "Governor.helpers.spec"
  4. /*
  5. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  6. โ”‚ Rule: propose effect and liveness. Includes "no double proposition" โ”‚
  7. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  8. */
  9. rule propose(uint256 pId, env e) {
  10. require nonpayable(e);
  11. require clockSanity(e);
  12. uint256 otherId;
  13. uint8 stateBefore = state(e, pId);
  14. uint8 otherStateBefore = state(e, otherId);
  15. uint256 otherVoteStart = proposalSnapshot(otherId);
  16. uint256 otherVoteEnd = proposalDeadline(otherId);
  17. address otherProposer = proposalProposer(otherId);
  18. address[] targets; uint256[] values; bytes[] calldatas; string descr;
  19. require pId == propose@withrevert(e, targets, values, calldatas, descr);
  20. bool success = !lastReverted;
  21. // liveness & double proposal
  22. assert success <=> stateBefore == UNSET();
  23. // effect
  24. assert success => (
  25. state(e, pId) == PENDING() &&
  26. proposalProposer(pId) == e.msg.sender &&
  27. proposalSnapshot(pId) == clock(e) + votingDelay() &&
  28. proposalDeadline(pId) == clock(e) + votingDelay() + votingPeriod()
  29. );
  30. // no side-effect
  31. assert state(e, otherId) != otherStateBefore => otherId == pId;
  32. assert proposalSnapshot(otherId) == otherVoteStart;
  33. assert proposalDeadline(otherId) == otherVoteEnd;
  34. assert proposalProposer(otherId) == otherProposer;
  35. }
  36. /*
  37. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  38. โ”‚ Rule: votes effect and liveness. Includes "A user cannot vote twice" โ”‚
  39. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  40. */
  41. rule castVote(uint256 pId, env e, method f)
  42. filtered { f -> voting(f) }
  43. {
  44. require nonpayable(e);
  45. require clockSanity(e);
  46. uint8 support;
  47. address voter;
  48. address otherVoter;
  49. uint256 otherId;
  50. uint8 stateBefore = state(e, pId);
  51. bool hasVotedBefore = hasVoted(pId, voter);
  52. bool otherVotedBefore = hasVoted(otherId, otherVoter);
  53. uint256 againstVotesBefore = getAgainstVotes(pId);
  54. uint256 forVotesBefore = getForVotes(pId);
  55. uint256 abstainVotesBefore = getAbstainVotes(pId);
  56. uint256 otherAgainstVotesBefore = getAgainstVotes(otherId);
  57. uint256 otherForVotesBefore = getForVotes(otherId);
  58. uint256 otherAbstainVotesBefore = getAbstainVotes(otherId);
  59. // voting weight overflow check
  60. uint256 voterWeight = token_getPastVotes(voter, proposalSnapshot(pId));
  61. require againstVotesBefore + voterWeight <= max_uint256;
  62. require forVotesBefore + voterWeight <= max_uint256;
  63. require abstainVotesBefore + voterWeight <= max_uint256;
  64. uint256 weight = helperVoteWithRevert(e, f, pId, voter, support);
  65. bool success = !lastReverted;
  66. assert success <=> (
  67. stateBefore == ACTIVE() &&
  68. !hasVotedBefore &&
  69. (support == 0 || support == 1 || support == 2)
  70. );
  71. assert success => (
  72. state(e, pId) == ACTIVE() &&
  73. voterWeight == weight &&
  74. getAgainstVotes(pId) == againstVotesBefore + (support == 0 ? weight : 0) &&
  75. getForVotes(pId) == forVotesBefore + (support == 1 ? weight : 0) &&
  76. getAbstainVotes(pId) == abstainVotesBefore + (support == 2 ? weight : 0) &&
  77. hasVoted(pId, voter)
  78. );
  79. // no side-effect
  80. assert hasVoted(otherId, otherVoter) != otherVotedBefore => (otherId == pId && otherVoter == voter);
  81. assert getAgainstVotes(otherId) != otherAgainstVotesBefore => (otherId == pId);
  82. assert getForVotes(otherId) != otherForVotesBefore => (otherId == pId);
  83. assert getAbstainVotes(otherId) != otherAbstainVotesBefore => (otherId == pId);
  84. }
  85. /*
  86. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  87. โ”‚ Rule: queue effect and liveness. โ”‚
  88. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  89. */
  90. rule queue(uint256 pId, env e) {
  91. require nonpayable(e);
  92. require clockSanity(e);
  93. uint256 otherId;
  94. uint8 stateBefore = state(e, pId);
  95. uint8 otherStateBefore = state(e, otherId);
  96. bool queuedBefore = isQueued(pId)
  97. bool otherQueuedBefore = isQueued(otherId)
  98. address[] targets; uint256[] values; bytes[] calldatas; bytes32 descrHash;
  99. require pId == queue@withrevert(e, targets, values, calldatas, descrHash);
  100. bool success = !lastReverted;
  101. // liveness
  102. assert success <=> stateBefore == SUCCEEDED();
  103. // effect
  104. assert success => (
  105. state(e, pId) == QUEUED()
  106. !queuedBefore &&
  107. isQueued(pId)
  108. );
  109. // no side-effect
  110. assert state(e, otherId) != otherStateBefore => otherId == pId;
  111. assert isQueued(otherId) != queuedBefore => otherId == pId;
  112. }
  113. /*
  114. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  115. โ”‚ Rule: execute effect and liveness. โ”‚
  116. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  117. */
  118. rule execute(uint256 pId, env e) {
  119. require nonpayable(e);
  120. require clockSanity(e);
  121. uint256 otherId;
  122. uint8 stateBefore = state(e, pId);
  123. uint8 otherStateBefore = state(e, otherId);
  124. address[] targets; uint256[] values; bytes[] calldatas; bytes32 descrHash;
  125. require pId == execute@withrevert(e, targets, values, calldatas, descrHash);
  126. bool success = !lastReverted;
  127. // liveness: can't check full equivalence because of execution call reverts
  128. assert success => (stateBefore == SUCCEEDED() || stateBefore == QUEUED());
  129. // effect
  130. assert success => (
  131. state(e, pId) == EXECUTED()
  132. );
  133. // no side-effect
  134. assert state(e, otherId) != otherStateBefore => otherId == pId;
  135. }
  136. /*
  137. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  138. โ”‚ Rule: cancel (public) effect and liveness. โ”‚
  139. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  140. */
  141. rule cancel(uint256 pId, env e) {
  142. require nonpayable(e);
  143. require clockSanity(e);
  144. uint256 otherId;
  145. uint8 stateBefore = state(e, pId);
  146. uint8 otherStateBefore = state(e, otherId);
  147. address[] targets; uint256[] values; bytes[] calldatas; bytes32 descrHash;
  148. require pId == cancel@withrevert(e, targets, values, calldatas, descrHash);
  149. bool success = !lastReverted;
  150. // liveness
  151. assert success <=> (
  152. stateBefore == PENDING() &&
  153. e.msg.sender == proposalProposer(pId)
  154. );
  155. // effect
  156. assert success => (
  157. state(e, pId) == CANCELED()
  158. );
  159. // no side-effect
  160. assert state(e, otherId) != otherStateBefore => otherId == pId;
  161. }