GovernorBase.spec 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. execute(address[], uint256[], bytes[], bytes32) returns uint256
  11. // initialized(uint256) returns bool envfree
  12. hasVoted(uint256, address) returns bool
  13. castVote(uint256, uint8) returns uint256
  14. // internal functions made public in harness:
  15. _quorumReached(uint256) returns bool envfree
  16. _voteSucceeded(uint256) returns bool envfree
  17. }
  18. //////////////////////////////////////////////////////////////////////////////
  19. ////////////////////////////// INVARIANTS ////////////////////////////////////
  20. //////////////////////////////////////////////////////////////////////////////
  21. /*
  22. * A proposal cannot end unless it started.
  23. */
  24. invariant voteStartBeforeVoteEnd(uint256 pId)
  25. (proposalSnapshot(pId) > 0 => proposalSnapshot(pId) < proposalDeadline(pId))
  26. && (proposalSnapshot(pId) == 0 => proposalDeadline(pId) == 0)
  27. /*
  28. * A proposal cannot be both executed and canceled.
  29. */
  30. invariant noBothExecutedAndCanceled(uint256 pId)
  31. !isExecuted(pId) || !isCanceled(pId)
  32. /*
  33. * A proposal cannot be neither executed nor canceled before it starts
  34. */
  35. invariant noExecuteOrCancelBeforeStarting(env e, uint256 pId)
  36. e.block.number < proposalSnapshot(pId)
  37. => !isExecuted(pId) && !isCanceled(pId)
  38. /*
  39. * A proposal could be executed only if quorum was reached and vote succeeded
  40. */
  41. invariant executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId)
  42. isExecuted(pId) => _quorumReached(pId) && _voteSucceeded(pId)
  43. //////////////////////////////////////////////////////////////////////////////
  44. /////////////////////////////////// RULES ////////////////////////////////////
  45. //////////////////////////////////////////////////////////////////////////////
  46. /*
  47. * The voting must start not before the proposal’s creation time
  48. */
  49. rule noStartBeforeCreation(uint256 pId) {
  50. uint previousStart = proposalSnapshot(pId);
  51. require previousStart == 0;
  52. env e;
  53. calldataarg arg;
  54. propose(e, arg);
  55. uint newStart = proposalSnapshot(pId);
  56. // if created, start is after creation
  57. assert(newStart != 0 => newStart >= e.block.number);
  58. }
  59. /*
  60. * Once a proposal is created, voteStart and voteEnd are immutable
  61. */
  62. rule immutableFieldsAfterProposalCreation(uint256 pId, method f) {
  63. uint _voteStart = proposalSnapshot(pId);
  64. uint _voteEnd = proposalDeadline(pId);
  65. require _voteStart > 0; // proposal was created
  66. env e;
  67. calldataarg arg;
  68. f(e, arg);
  69. uint voteStart_ = proposalSnapshot(pId);
  70. uint voteEnd_ = proposalDeadline(pId);
  71. assert _voteStart == voteStart_;
  72. assert _voteEnd == voteEnd_;
  73. }
  74. /*
  75. * A user cannot vote twice
  76. */
  77. rule doubleVoting(uint256 pId, uint8 sup) {
  78. env e;
  79. address user = e.msg.sender;
  80. bool votedCheck = hasVoted(e, pId, user);
  81. require votedCheck == true;
  82. castVote@withrevert(e, pId, sup);
  83. bool reverted = lastReverted;
  84. assert votedCheck => reverted, "double voting accured";
  85. }
  86. /*
  87. * When a proposal is created the start and end date are created in the future.
  88. */
  89. rule proposalCreatedStartAndEndDateInFuture(address[] targets, uint256[] values, bytes[] calldatas){
  90. env e;
  91. uint256 pId = callPropose(e, targets, values, calldatas);
  92. uint256 startDate = proposalSnapshot(pId);
  93. uint256 endDate = proposalDeadline(pId);
  94. assert(startDate >= e.block.number && endDate >= e.block.number, "Start or end date were set in the past");
  95. }
  96. /**
  97. * Check hashProposal hashing is reliable (different inputs lead to different buffers hashed)
  98. */
  99. /*
  100. rule checkHashProposal {
  101. address[] t1;
  102. address[] t2;
  103. uint256[] v1;
  104. uint256[] v2;
  105. bytes[] c1;
  106. bytes[] c2;
  107. bytes32 d1;
  108. bytes32 d2;
  109. uint256 h1 = hashProposal(t1,v1,c1,d1);
  110. uint256 h2 = hashProposal(t2,v2,c2,d2);
  111. bool equalHashes = h1 == h2;
  112. assert equalHashes => t1.length == t2.length;
  113. assert equalHashes => v1.length == v2.length;
  114. assert equalHashes => c1.length == c2.length;
  115. assert equalHashes => d1 == d2;
  116. }
  117. */