GovernorFunctions.spec 4.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. uint256 otherId;
  12. uint8 stateBefore = state(e, pId);
  13. uint8 otherStateBefore = state(e, otherId);
  14. uint256 otherVoteStart = proposalSnapshot(otherId);
  15. uint256 otherVoteEnd = proposalDeadline(otherId);
  16. address otherProposer = proposalProposer(otherId);
  17. address[] targets; uint256[] values; bytes[] calldatas; string reason;
  18. require pId == propose@withrevert(e, targets, values, calldatas, reason);
  19. bool success = !lastReverted;
  20. // liveness & double proposal
  21. assert success <=> stateBefore == UNSET();
  22. // effect
  23. assert success => (
  24. state(e, pId) == PENDING() &&
  25. proposalProposer(pId) == e.msg.sender &&
  26. proposalSnapshot(pId) == clock(e) + votingDelay() &&
  27. proposalDeadline(pId) == clock(e) + votingDelay() + votingPeriod()
  28. );
  29. // no side-effect
  30. assert state(e, otherId) != otherStateBefore => otherId == pId;
  31. assert proposalSnapshot(otherId) == otherVoteStart;
  32. assert proposalDeadline(otherId) == otherVoteEnd;
  33. assert proposalProposer(otherId) == otherProposer;
  34. }
  35. /*
  36. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  37. โ”‚ Rule: votes effect and liveness. Includes "A user cannot vote twice" โ”‚
  38. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  39. */
  40. rule castVote(uint256 pId, env e, method f)
  41. filtered { f -> voting(f) }
  42. {
  43. require nonpayable(e);
  44. uint8 support;
  45. address voter;
  46. address otherVoter;
  47. uint256 otherId;
  48. uint8 stateBefore = state(e, pId);
  49. bool hasVotedBefore = hasVoted(pId, voter);
  50. bool otherVotedBefore = hasVoted(otherId, otherVoter);
  51. uint256 againstVotesBefore = getAgainstVotes(pId);
  52. uint256 forVotesBefore = getForVotes(pId);
  53. uint256 abstainVotesBefore = getAbstainVotes(pId);
  54. uint256 otherAgainstVotesBefore = getAgainstVotes(otherId);
  55. uint256 otherForVotesBefore = getForVotes(otherId);
  56. uint256 otherAbstainVotesBefore = getAbstainVotes(otherId);
  57. // voting weight overflow check
  58. uint256 voterWeight = token_getPastVotes(voter, proposalSnapshot(pId));
  59. require againstVotesBefore + voterWeight <= max_uint256;
  60. require forVotesBefore + voterWeight <= max_uint256;
  61. require abstainVotesBefore + voterWeight <= max_uint256;
  62. uint256 weight = helperVoteWithRevert(e, f, pId, voter, support);
  63. bool success = !lastReverted;
  64. assert success <=> (
  65. stateBefore == ACTIVE() &&
  66. !hasVotedBefore &&
  67. (support == 0 || support == 1 || support == 2)
  68. );
  69. assert success => (
  70. state(e, pId) == ACTIVE() &&
  71. voterWeight == weight &&
  72. getAgainstVotes(pId) == againstVotesBefore + (support == 0 ? weight : 0) &&
  73. getForVotes(pId) == forVotesBefore + (support == 1 ? weight : 0) &&
  74. getAbstainVotes(pId) == abstainVotesBefore + (support == 2 ? weight : 0) &&
  75. hasVoted(pId, voter)
  76. );
  77. // no side-effect
  78. assert hasVoted(otherId, otherVoter) != otherVotedBefore => (otherId == pId && otherVoter == voter);
  79. assert getAgainstVotes(otherId) != otherAgainstVotesBefore => (otherId == pId);
  80. assert getForVotes(otherId) != otherForVotesBefore => (otherId == pId);
  81. assert getAbstainVotes(otherId) != otherAbstainVotesBefore => (otherId == pId);
  82. }