Governor.helpers.spec 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import "helpers.spec"
  2. import "methods/IGovernor.spec"
  3. import "methods/ITimelockController.spec"
  4. /*
  5. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  6. โ”‚ Sanity โ”‚
  7. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  8. */
  9. function clockSanity(env e) returns bool {
  10. return e.block.number < max_uint48()
  11. && e.block.timestamp < max_uint48()
  12. && clock(e) > 0;
  13. }
  14. function validProposal(address[] targets, uint256[] values, bytes[] calldatas) returns bool {
  15. return targets.length > 0
  16. && targets.length == values.length
  17. && targets.length == calldatas.length;
  18. }
  19. function sanityString(string s) returns bool {
  20. return s.length < 0xffff;
  21. }
  22. function sanityBytes(bytes b) returns bool {
  23. return b.length < 0xffff;
  24. }
  25. /*
  26. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  27. โ”‚ States โ”‚
  28. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  29. */
  30. definition UNSET() returns uint8 = 255;
  31. definition PENDING() returns uint8 = 0;
  32. definition ACTIVE() returns uint8 = 1;
  33. definition CANCELED() returns uint8 = 2;
  34. definition DEFEATED() returns uint8 = 3;
  35. definition SUCCEEDED() returns uint8 = 4;
  36. definition QUEUED() returns uint8 = 5;
  37. definition EXPIRED() returns uint8 = 6;
  38. definition EXECUTED() returns uint8 = 7;
  39. // This helper is an alternative to state(e, pId) that will return UNSET() instead of reverting when then proposal
  40. // does not exist (not created yet)
  41. function safeState(env e, uint256 pId) returns uint8 {
  42. return proposalCreated(pId) ? state(e, pId): UNSET();
  43. }
  44. definition proposalCreated(uint256 pId) returns bool =
  45. proposalSnapshot(pId) > 0 && proposalDeadline(pId) > 0 && proposalProposer(pId) != 0;
  46. /*
  47. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  48. โ”‚ Filters โ”‚
  49. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  50. */
  51. definition assumedSafe(method f) returns bool =
  52. f.isView ||
  53. f.isFallback ||
  54. f.selector == relay(address,uint256,bytes).selector ||
  55. f.selector == onERC721Received(address,address,uint256,bytes).selector ||
  56. f.selector == onERC1155Received(address,address,uint256,uint256,bytes).selector ||
  57. f.selector == onERC1155BatchReceived(address,address,uint256[],uint256[],bytes).selector;
  58. // These function are covered by helperFunctionsWithRevert
  59. definition operateOnProposal(method f) returns bool =
  60. f.selector == propose(address[],uint256[],bytes[],string).selector ||
  61. f.selector == queue(address[],uint256[],bytes[],bytes32).selector ||
  62. f.selector == execute(address[],uint256[],bytes[],bytes32).selector ||
  63. f.selector == cancel(address[],uint256[],bytes[],bytes32).selector ||
  64. f.selector == castVote(uint256,uint8).selector ||
  65. f.selector == castVoteWithReason(uint256,uint8,string).selector ||
  66. f.selector == castVoteWithReasonAndParams(uint256,uint8,string,bytes).selector ||
  67. f.selector == castVoteBySig(uint256,uint8,uint8,bytes32,bytes32).selector ||
  68. f.selector == castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32).selector
  69. // These function are covered by helperVoteWithRevert
  70. definition voting(method f) returns bool =
  71. f.selector == castVote(uint256,uint8).selector ||
  72. f.selector == castVoteWithReason(uint256,uint8,string).selector ||
  73. f.selector == castVoteWithReasonAndParams(uint256,uint8,string,bytes).selector;
  74. definition votingBySig(method f) returns bool =
  75. f.selector == castVoteBySig(uint256,uint8,uint8,bytes32,bytes32).selector ||
  76. f.selector == castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32).selector;
  77. definition votingAll(method f) returns bool =
  78. voting(f) || votingBySig(f);
  79. /*
  80. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  81. โ”‚ Helper functions โ”‚
  82. โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  83. */
  84. function helperVoteWithRevert(env e, method f, uint256 pId, address voter, uint8 support) returns uint256 {
  85. if (f.selector == castVote(uint256,uint8).selector)
  86. {
  87. require e.msg.sender == voter;
  88. return castVote@withrevert(e, pId, support);
  89. }
  90. else if (f.selector == castVoteWithReason(uint256,uint8,string).selector)
  91. {
  92. string reason;
  93. require e.msg.sender == voter && sanityString(reason);
  94. return castVoteWithReason@withrevert(e, pId, support, reason);
  95. }
  96. else if (f.selector == castVoteWithReasonAndParams(uint256,uint8,string,bytes).selector)
  97. {
  98. string reason; bytes params;
  99. require e.msg.sender == voter && sanityString(reason) && sanityBytes(params);
  100. return castVoteWithReasonAndParams@withrevert(e, pId, support, reason, params);
  101. }
  102. else
  103. {
  104. calldataarg args;
  105. f(e, args);
  106. return 0;
  107. }
  108. }
  109. // Governor function that operates on a given proposalId may or may not include the proposalId in the arguments. This
  110. // helper restricts the call to method `f` in a way that it's operating on a specific proposal.
  111. //
  112. // This can be used to say "consider any function call that operates on proposal `pId`" or "consider a propose call
  113. // that corresponds to a given pId".
  114. //
  115. // This is for example used when proving that not 2 proposals can be proposed with the same id: Once the proposal is
  116. // proposed a first time, we want to prove that "any propose call that corresponds to the same id should revert".
  117. function helperFunctionsWithRevert(env e, method f, uint256 pId) {
  118. if (f.selector == propose(address[],uint256[],bytes[],string).selector)
  119. {
  120. address[] targets; uint256[] values; bytes[] calldatas; string descr;
  121. require pId == hashProposal(targets, values, calldatas, descr);
  122. propose@withrevert(e, targets, values, calldatas, descr);
  123. }
  124. else if (f.selector == queue(address[],uint256[],bytes[],bytes32).selector)
  125. {
  126. address[] targets; uint256[] values; bytes[] calldatas; bytes32 descrHash;
  127. require pId == hashProposal(targets, values, calldatas, descrHash);
  128. queue@withrevert(e, targets, values, calldatas, descrHash);
  129. }
  130. else if (f.selector == execute(address[],uint256[],bytes[],bytes32).selector)
  131. {
  132. address[] targets; uint256[] values; bytes[] calldatas; bytes32 descrHash;
  133. require pId == hashProposal(targets, values, calldatas, descrHash);
  134. execute@withrevert(e, targets, values, calldatas, descrHash);
  135. }
  136. else if (f.selector == cancel(address[],uint256[],bytes[],bytes32).selector)
  137. {
  138. address[] targets; uint256[] values; bytes[] calldatas; bytes32 descrHash;
  139. require pId == hashProposal(targets, values, calldatas, descrHash);
  140. cancel@withrevert(e, targets, values, calldatas, descrHash);
  141. }
  142. else if (f.selector == castVote(uint256,uint8).selector)
  143. {
  144. uint8 support;
  145. castVote@withrevert(e, pId, support);
  146. }
  147. else if (f.selector == castVoteWithReason(uint256,uint8,string).selector)
  148. {
  149. uint8 support; string reason;
  150. castVoteWithReason@withrevert(e, pId, support, reason);
  151. }
  152. else if (f.selector == castVoteWithReasonAndParams(uint256,uint8,string,bytes).selector)
  153. {
  154. uint8 support; string reason; bytes params;
  155. castVoteWithReasonAndParams@withrevert(e, pId, support, reason, params);
  156. }
  157. else if (f.selector == castVoteBySig(uint256,uint8,uint8,bytes32,bytes32).selector)
  158. {
  159. uint8 support; uint8 v; bytes32 r; bytes32 s;
  160. castVoteBySig@withrevert(e, pId, support, v, r, s);
  161. }
  162. else if (f.selector == castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32).selector)
  163. {
  164. uint8 support; string reason; bytes params; uint8 v; bytes32 r; bytes32 s;
  165. castVoteWithReasonAndParamsBySig@withrevert(e, pId, support, reason, params, v, r, s);
  166. }
  167. else
  168. {
  169. calldataarg args;
  170. f(e, args);
  171. }
  172. }