GovernorBase.spec 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Governor.sol base definitions
  2. methods {
  3. proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
  4. proposalDeadline(uint256) returns uint256 envfree
  5. hashProposal(address[],uint256[],bytes[],bytes32) returns uint256 envfree
  6. isExecuted(uint256) returns bool envfree
  7. isCanceled(uint256) returns bool envfree
  8. // internal functions made public in harness:
  9. _quorumReached(uint256) returns bool envfree
  10. _voteSucceeded(uint256) returns bool envfree
  11. }
  12. //////////////////////////////////////////////////////////////////////////////
  13. ////////////////////////////// INVARIANTS ////////////////////////////////////
  14. //////////////////////////////////////////////////////////////////////////////
  15. /**
  16. * A proposal cannot end unless it started.
  17. */
  18. //invariant voteStartBeforeVoteEnd1(uint256 pId) proposalSnapshot(pId) < proposalDeadline(pId)
  19. invariant voteStartBeforeVoteEnd(uint256 pId)
  20. (proposalSnapshot(pId) == 0 <=> proposalDeadline(pId) == 0) &&
  21. proposalSnapshot(pId) < proposalDeadline(pId)
  22. /**
  23. * A proposal cannot be both executed and canceled.
  24. */
  25. invariant noBothExecutedAndCanceled(uint256 pId) !isExecuted(pId) || !isCanceled(pId)
  26. /**
  27. * A proposal cannot be neither executed nor canceled before it starts
  28. */
  29. invariant noExecuteOrCancelBeforeStarting(env e, uint256 pId) e.block.number < proposalSnapshot(pId)
  30. => !isExecuted(pId) && !isCanceled(pId)
  31. /**
  32. * A proposal could be executed only if quorum was reached and vote succeeded
  33. */
  34. invariant executionOnlyIfQuoromReachedAndVoteSucceeded(uint256 pId) isExecuted(pId) => _quorumReached(pId) && _voteSucceeded(pId)
  35. //////////////////////////////////////////////////////////////////////////////
  36. /////////////////////////////////// RULES ////////////////////////////////////
  37. //////////////////////////////////////////////////////////////////////////////
  38. /**
  39. * The voting must start not before the proposal’s creation time
  40. */
  41. rule noStartBeforeCreation(uint256 pId) {
  42. uint previousStart = proposalSnapshot(pId);
  43. require previousStart == 0;
  44. env e;
  45. calldataarg arg;
  46. propose(e, arg);
  47. uint newStart = proposalSnapshot(pId);
  48. // if created, start is after creation
  49. assert newStart != 0 => newStart >= e.block.number;
  50. }
  51. /**
  52. * Check hashProposal hashing is reliable (different inputs lead to different buffers hashed)
  53. */
  54. /*
  55. rule checkHashProposal {
  56. address[] t1;
  57. address[] t2;
  58. uint256[] v1;
  59. uint256[] v2;
  60. bytes[] c1;
  61. bytes[] c2;
  62. bytes32 d1;
  63. bytes32 d2;
  64. uint256 h1 = hashProposal(t1,v1,c1,d1);
  65. uint256 h2 = hashProposal(t2,v2,c2,d2);
  66. bool equalHashes = h1 == h2;
  67. assert equalHashes => t1.length == t2.length;
  68. assert equalHashes => v1.length == v2.length;
  69. assert equalHashes => c1.length == c2.length;
  70. assert equalHashes => d1 == d2;
  71. }
  72. */
  73. /**
  74. * Once a proposal is created, voteStart and voteEnd are immutable
  75. */
  76. rule immutableFieldsAfterProposalCreation(uint256 pId, method f) {
  77. uint _voteStart = proposalSnapshot(pId);
  78. uint _voteEnd = proposalDeadline(pId);
  79. require _voteStart > 0; // proposal was created
  80. env e;
  81. calldataarg arg;
  82. f(e, arg);
  83. uint voteStart_ = proposalSnapshot(pId);
  84. uint voteEnd_ = proposalDeadline(pId);
  85. assert _voteStart == voteStart_;
  86. assert _voteEnd == voteEnd_;
  87. }