GovernorBase.spec 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //////////////////////////////////////////////////////////////////////////////
  2. ///////////////////// Governor.sol base definitions //////////////////////////
  3. //////////////////////////////////////////////////////////////////////////////
  4. methods {
  5. proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
  6. proposalDeadline(uint256) returns uint256 envfree
  7. hashProposal(address[],uint256[],bytes[],bytes32) returns uint256 envfree
  8. isExecuted(uint256) returns bool envfree
  9. isCanceled(uint256) returns bool envfree
  10. // initialized(uint256) returns bool envfree
  11. hasVoted(uint256, address) returns bool
  12. castVote(uint256, uint8) returns uint256
  13. // internal functions made public in harness:
  14. _quorumReached(uint256) returns bool envfree
  15. _voteSucceeded(uint256) returns bool envfree
  16. // getter for checking the sums
  17. counter_vote_power_by_id(uint256) returns uint256 envfree
  18. ghost_sum_vote_power_by_id(uint256) returns uint256 envfree
  19. counted_weight(uint256) returns uint256 envfree
  20. }
  21. //////////////////////////////////////////////////////////////////////////////
  22. ////////////////////////////// INVARIANTS ////////////////////////////////////
  23. //////////////////////////////////////////////////////////////////////////////
  24. /**
  25. * A proposal cannot end unless it started.
  26. */
  27. //invariant voteStartBeforeVoteEnd1(uint256 pId) proposalSnapshot(pId) < proposalDeadline(pId)
  28. invariant voteStartBeforeVoteEnd(uint256 pId)
  29. (proposalSnapshot(pId) > 0 => proposalSnapshot(pId) < proposalDeadline(pId))
  30. && (proposalSnapshot(pId) == 0 => proposalDeadline(pId) == 0)
  31. /*
  32. proposalSnapshot(pId) < proposalDeadline(pId) || (proposalSnapshot(pId) == 0 && proposalDeadline(pId) == 0)
  33. { preserved {
  34. require initialized(pId) == true;
  35. }}
  36. */
  37. /**
  38. * A proposal cannot be both executed and canceled.
  39. */
  40. invariant noBothExecutedAndCanceled(uint256 pId)
  41. !isExecuted(pId) || !isCanceled(pId)
  42. /**
  43. * A proposal cannot be neither executed nor canceled before it starts
  44. */
  45. invariant noExecuteOrCancelBeforeStarting(env e, uint256 pId)
  46. e.block.number < proposalSnapshot(pId)
  47. => !isExecuted(pId) && !isCanceled(pId)
  48. /**
  49. * A proposal could be executed only if quorum was reached and vote succeeded
  50. */
  51. invariant executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId)
  52. isExecuted(pId) => _quorumReached(pId) && _voteSucceeded(pId)
  53. /*
  54. * No functions should be allowed to run after a job is deemed as canceled
  55. */
  56. rule cannotSetIfCanceled(uint256 pId, method f) filtered { f-> !f.isView }{
  57. require(isCanceled(pId));
  58. env e; calldataarg args;
  59. f(e, args);
  60. assert(isCanceled(pId) => lastReverted == true, "Function did not revert when canceled");
  61. }
  62. /*
  63. * No functions should be allowed to run after a job is deemed as executed
  64. */
  65. rule cannotSetIfExecuted(uint256 pId, method f) filtered { f-> !f.isView }{
  66. require(isExecuted(pId));
  67. env e; calldataarg args;
  68. f(e, args);
  69. assert(isExecuted(pId) => lastReverted == true, "Function did not revert after executed");
  70. }
  71. //////////////////////////////////////////////////////////////////////////////
  72. /////////////////////////////////// RULES ////////////////////////////////////
  73. //////////////////////////////////////////////////////////////////////////////
  74. /**
  75. * The voting must start not before the proposal’s creation time
  76. */
  77. rule noStartBeforeCreation(uint256 pId) {
  78. uint previousStart = proposalSnapshot(pId);
  79. require previousStart == 0;
  80. env e;
  81. calldataarg arg;
  82. propose(e, arg);
  83. uint newStart = proposalSnapshot(pId);
  84. // if created, start is after creation
  85. assert newStart != 0 => newStart >= e.block.number;
  86. }
  87. /**
  88. * Check hashProposal hashing is reliable (different inputs lead to different buffers hashed)
  89. */
  90. /*
  91. rule checkHashProposal {
  92. address[] t1;
  93. address[] t2;
  94. uint256[] v1;
  95. uint256[] v2;
  96. bytes[] c1;
  97. bytes[] c2;
  98. bytes32 d1;
  99. bytes32 d2;
  100. uint256 h1 = hashProposal(t1,v1,c1,d1);
  101. uint256 h2 = hashProposal(t2,v2,c2,d2);
  102. bool equalHashes = h1 == h2;
  103. assert equalHashes => t1.length == t2.length;
  104. assert equalHashes => v1.length == v2.length;
  105. assert equalHashes => c1.length == c2.length;
  106. assert equalHashes => d1 == d2;
  107. }
  108. */
  109. /**
  110. * Once a proposal is created, voteStart and voteEnd are immutable
  111. */
  112. rule immutableFieldsAfterProposalCreation(uint256 pId, method f) {
  113. uint _voteStart = proposalSnapshot(pId);
  114. uint _voteEnd = proposalDeadline(pId);
  115. require _voteStart > 0; // proposal was created
  116. env e;
  117. calldataarg arg;
  118. f(e, arg);
  119. uint voteStart_ = proposalSnapshot(pId);
  120. uint voteEnd_ = proposalDeadline(pId);
  121. assert _voteStart == voteStart_;
  122. assert _voteEnd == voteEnd_;
  123. }
  124. /**
  125. * Check if it's possible to vote two time. Relevant to GovernorCountingSimpleHarness.sol contract
  126. */
  127. rule doubleVoting(uint256 pId, uint8 sup) {
  128. env e;
  129. address user = e.msg.sender;
  130. bool votedCheck = hasVoted(e, pId, user);
  131. require votedCheck == true;
  132. castVote@withrevert(e, pId, sup);
  133. bool reverted = lastReverted;
  134. assert votedCheck => reverted, "double voting accured";
  135. }