GovernorBase.spec 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Governor.sol base definitions
  2. methods {
  3. proposalSnapshot(uint256) returns uint256 envfree // matches proposalVoteStart
  4. }
  5. ghost proposalVoteStart(uint256) returns uint64 {
  6. init_state axiom forall uint256 pId. proposalVoteStart(pId) == 0;
  7. }
  8. ghost proposalVoteEnd(uint256) returns uint64 {
  9. init_state axiom forall uint256 pId. proposalVoteEnd(pId) == 0;
  10. }
  11. ghost proposalExecuted(uint256) returns bool {
  12. init_state axiom forall uint256 pId. !proposalExecuted(pId);
  13. }
  14. ghost proposalCanceled(uint256) returns bool {
  15. init_state axiom forall uint256 pId. !proposalCanceled(pId);
  16. }
  17. hook Sstore _proposals[KEY uint256 pId].(offset 0).(offset 0) uint64 newValue STORAGE {
  18. havoc proposalVoteStart assuming (
  19. proposalVoteStart@new(pId) == newValue
  20. && (forall uint256 pId2. pId != pId2 => proposalVoteStart@new(pId2) == proposalVoteStart@old(pId2))
  21. );
  22. }
  23. hook Sload uint64 value _proposals[KEY uint256 pId].(offset 0).(offset 0) STORAGE {
  24. require proposalVoteStart(pId) == value;
  25. }
  26. hook Sstore _proposals[KEY uint256 pId].(offset 32).(offset 0) uint64 newValue STORAGE {
  27. havoc proposalVoteEnd assuming (
  28. proposalVoteEnd@new(pId) == newValue
  29. && (forall uint256 pId2. pId != pId2 => proposalVoteEnd@new(pId2) == proposalVoteEnd@old(pId2))
  30. );
  31. }
  32. hook Sload uint64 value _proposals[KEY uint256 pId].(offset 32).(offset 0) STORAGE {
  33. require proposalVoteEnd(pId) == value;
  34. }
  35. rule sanityCheckVoteStart(method f, uint256 pId) {
  36. uint64 preGhost = proposalVoteStart(pId);
  37. uint256 pre = proposalSnapshot(pId);
  38. env e;
  39. calldataarg arg;
  40. f(e, arg);
  41. uint64 postGhost = proposalVoteStart(pId);
  42. uint256 post = proposalSnapshot(pId);
  43. assert preGhost == postGhost <=> pre == post, "ghost changes are correlated with getter changes";
  44. assert pre == preGhost => post == postGhost, "if correlated at the beginning should be correlated at the end";
  45. }
  46. rule sanityCheckVoteEnd(method f, uint256 pId) {
  47. uint64 preGhost = proposalVoteEnd(pId);
  48. uint256 pre = proposalSnapshot(pId);
  49. env e;
  50. calldataarg arg;
  51. f(e, arg);
  52. uint64 postGhost = proposalVoteEnd(pId);
  53. uint256 post = proposalSnapshot(pId);
  54. assert preGhost == postGhost <=> pre == post, "ghost changes are correlated with getter changes";
  55. assert pre == preGhost => post == postGhost, "if correlated at the beginning should be correlated at the end";
  56. }
  57. /**
  58. * A proposal cannot end unless it started.
  59. */
  60. invariant voteStartBeforeVoteEnd(uint256 pId) proposalVoteStart(pId) < proposalVoteEnd(pId)
  61. /**
  62. * A proposal cannot be both executed and canceled.
  63. */
  64. invariant noBothExecutedAndCanceled(uint256 pId) !proposalExecuted(pId) || !proposalCanceled(pId)