TimelockController.spec 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using AccessControlHarness as AC
  2. methods {
  3. getTimestamp(bytes32) returns(uint256) envfree
  4. _DONE_TIMESTAMP() returns(uint256) envfree
  5. _minDelay() returns(uint256) envfree
  6. getMinDelay() returns(uint256) envfree
  7. hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) returns(bytes32) envfree
  8. cancel(bytes32)
  9. schedule(address, uint256, bytes32, bytes32, bytes32, uint256)
  10. execute(address, uint256, bytes, bytes32, bytes32)
  11. }
  12. ////////////////////////////////////////////////////////////////////////////
  13. // Definitions //
  14. ////////////////////////////////////////////////////////////////////////////
  15. definition unset(bytes32 id) returns bool =
  16. getTimestamp(id) == 0;
  17. definition pending(bytes32 id) returns bool =
  18. getTimestamp(id) > _DONE_TIMESTAMP();
  19. definition ready(bytes32 id, env e) returns bool =
  20. getTimestamp(id) > _DONE_TIMESTAMP() && getTimestamp(id) <= e.block.timestamp;
  21. definition done(bytes32 id) returns bool =
  22. getTimestamp(id) == _DONE_TIMESTAMP();
  23. ////////////////////////////////////////////////////////////////////////////
  24. // Functions //
  25. ////////////////////////////////////////////////////////////////////////////
  26. function hashIdCorrelation(bytes32 id, address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt){
  27. require data.length < 7;
  28. require hashOperation(target, value, data, predecessor, salt) == id;
  29. }
  30. function executionsCall(method f, env e, address target, uint256 value, bytes data,
  31. bytes32 predecessor, bytes32 salt, uint256 delay,
  32. address[] targets, uint256[] values, bytes[] datas) {
  33. if (f.selector == execute(address, uint256, bytes, bytes32, bytes32).selector) {
  34. execute(e, target, value, data, predecessor, salt);
  35. } else if (f.selector == executeBatch(address[], uint256[], bytes[], bytes32, bytes32).selector) {
  36. executeBatch(e, targets, values, datas, predecessor, salt);
  37. } else {
  38. calldataarg args;
  39. f(e, args);
  40. }
  41. }
  42. ////////////////////////////////////////////////////////////////////////////
  43. // Ghosts //
  44. ////////////////////////////////////////////////////////////////////////////
  45. ////////////////////////////////////////////////////////////////////////////
  46. // Invariants //
  47. ////////////////////////////////////////////////////////////////////////////
  48. ////////////////////////////////////////////////////////////////////////////
  49. // Rules //
  50. ////////////////////////////////////////////////////////////////////////////
  51. rule keccakCheck(method f, env e){
  52. address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;
  53. address targetRand; uint256 valueRand; bytes dataRand; bytes32 predecessorRand; bytes32 saltRand;
  54. require data.length < 4;
  55. // uint256 freshIndex;
  56. // require freshIndex <= data.length
  57. // require target != targetRand || value != valueRand || data[freshIndex] != dataRand[freshIndex] || predecessor != predecessorRand || salt != saltRand;
  58. bytes32 a = hashOperation(target, value, data, predecessor, salt);
  59. bytes32 b = hashOperation(target, value, data, predecessor, salt);
  60. // bytes32 c = hashOperation(targetRand, valueRand, dataRand, predecessorRand, saltRand);
  61. assert a == b, "hashes are different";
  62. // assert a != c, "hashes are the same";
  63. }
  64. /////////////////////////////////////////////////////////////
  65. // STATE TRANSITIONS
  66. /////////////////////////////////////////////////////////////
  67. // STATUS - verified
  68. // unset() -> unset() || pending() only
  69. rule unsetPendingTransitionGeneral(method f, env e){
  70. bytes32 id;
  71. require unset(id);
  72. require e.block.timestamp > 1;
  73. calldataarg args;
  74. f(e, args);
  75. assert pending(id) || unset(id);
  76. }
  77. // STATUS -
  78. // unset() -> pending() via schedule() and scheduleBatch() only
  79. rule unsetPendingTransitionMethods(method f, env e){
  80. bytes32 id;
  81. require unset(id);
  82. calldataarg args;
  83. f(e, args);
  84. bool tmp = pending(id);
  85. assert pending(id) => (f.selector == schedule(address, uint256, bytes, bytes32, bytes32, uint256).selector
  86. || f.selector == scheduleBatch(address[], uint256[], bytes[], bytes32, bytes32, uint256).selector), "Why do we need to follow the schedule?";
  87. }
  88. // STATUS - verified
  89. // ready() -> done() via execute() and executeBatch() only
  90. rule readyDoneTransition(method f, env e){
  91. bytes32 id;
  92. require ready(id, e);
  93. calldataarg args;
  94. f(e, args);
  95. assert done(id) => f.selector == execute(address, uint256, bytes, bytes32, bytes32).selector
  96. || f.selector == executeBatch(address[], uint256[], bytes[], bytes32, bytes32).selector , "It's not done yet!";
  97. }
  98. // STATUS - verified
  99. // pending() -> cancelled() via cancel() only
  100. rule pendingCancelledTransition(method f, env e){
  101. bytes32 id;
  102. require pending(id);
  103. calldataarg args;
  104. f(e, args);
  105. assert unset(id) => f.selector == cancel(bytes32).selector, "How you dare to cancel me?";
  106. }
  107. // STATUS - verified
  108. // done() -> nowhere
  109. rule doneToNothingTransition(method f, env e){
  110. bytes32 id;
  111. require done(id);
  112. calldataarg args;
  113. f(e, args);
  114. assert done(id), "Did you find a way to escape? There is no way! HA-HA-HA";
  115. }
  116. /////////////////////////////////////////////////////////////
  117. // THE REST
  118. /////////////////////////////////////////////////////////////
  119. // STATUS - verified
  120. // only TimelockController contract can change minDealy
  121. rule minDealyOnlyChange(method f, env e){
  122. uint256 delayBefore = _minDelay();
  123. calldataarg args;
  124. f(e, args);
  125. uint256 delayAfter = _minDelay();
  126. assert delayBefore != delayAfter => e.msg.sender == currentContract, "You cannot change your destiny! Only I can!";
  127. }
  128. // STATUS - in progress (need working hash)
  129. // execute() is the only way to set timestamp to 1
  130. rule getTimestampOnlyChange(method f, env e){
  131. bytes32 id;
  132. address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt; uint256 delay;
  133. address[] targets; uint256[] values; bytes[] datas;
  134. require (targets[0] == target && values[0] == value && datas[0] == data)
  135. || (targets[1] == target && values[1] == value && datas[1] == data)
  136. || (targets[2] == target && values[2] == value && datas[2] == data);
  137. hashIdCorrelation(id, target, value, data, predecessor, salt);
  138. executionsCall(f, e, target, value, data, predecessor, salt, delay, targets, values, datas);
  139. assert getTimestamp(id) == 1 => f.selector == execute(address, uint256, bytes, bytes32, bytes32).selector
  140. || f.selector == executeBatch(address[], uint256[], bytes[], bytes32, bytes32).selector, "Did you find a way to break the system?";
  141. }
  142. // STATUS - in progress (need working hash)
  143. // scheduled operation timestamp == block.timestamp + delay (kind of unit test)
  144. rule scheduleCheck(method f, env e){
  145. bytes32 id;
  146. address target; uint256 value; bytes data ;bytes32 predecessor; bytes32 salt; uint256 delay;
  147. require getTimestamp(id) < e.block.timestamp;
  148. // require getMinDelay() > 0;
  149. hashIdCorrelation(id, target, value, data, predecessor, salt);
  150. schedule(e, target, value, data, predecessor, salt, delay);
  151. assert getTimestamp(id) == to_uint256(e.block.timestamp + getMinDelay()), "Time doesn't obey to mortal souls";
  152. }
  153. // STATUS - in progress (need working hash)
  154. // Cannot call execute on a pending (not ready) operation
  155. rule cannotCallExecute(method f, env e){
  156. address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;
  157. bytes32 id;
  158. hashIdCorrelation(id, target, value, data, predecessor, salt);
  159. require pending(id) && !ready(id, e);
  160. execute@withrevert(e, target, value, data, predecessor, salt);
  161. assert lastReverted, "you go against execution nature";
  162. }
  163. // STATUS - in progress
  164. // in unset() execute() reverts
  165. rule executeRevertFromUnset(method f, env e, env e2){
  166. address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;
  167. bytes32 id;
  168. hashIdCorrelation(id, target, value, data, predecessor, salt);
  169. require unset(id);
  170. execute@withrevert(e, target, value, data, predecessor, salt);
  171. assert lastReverted, "you go against execution nature";
  172. }
  173. // STATUS -
  174. // Execute reverts => state returns to pending
  175. rule executeRevertEffectCheck(method f, env e){
  176. address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;
  177. bytes32 id;
  178. hashIdCorrelation(id, target, value, data, predecessor, salt);
  179. require pending(id) && !ready(id, e);
  180. execute@withrevert(e, target, value, data, predecessor, salt);
  181. bool reverted = lastReverted;
  182. assert lastReverted => pending(id) && !ready(id, e), "you go against execution nature";
  183. }
  184. // STATUS - verified
  185. // Canceled operations cannot be executed → can’t move from canceled to ready
  186. rule cancelledNotExecuted(method f, env e){
  187. bytes32 id;
  188. require unset(id);
  189. require e.block.timestamp > 1;
  190. calldataarg args;
  191. f(e, args);
  192. assert !done(id), "The ship is not a creature of the air";
  193. }
  194. // STATUS - in progress (add schedule batch)
  195. // Only proposers can schedule an operation
  196. rule onlyProposer(method f, env e){
  197. bytes32 id;
  198. bytes32 role;
  199. address target; uint256 value; bytes data ;bytes32 predecessor; bytes32 salt; uint256 delay;
  200. require unset(id);
  201. hashIdCorrelation(id, target, value, data, predecessor, salt);
  202. AC._checkRole@withrevert(e, role);
  203. bool isCheckRoleReverted = lastReverted;
  204. schedule@withrevert(e, target, value, data, predecessor, salt, delay);
  205. bool isScheduleReverted = lastReverted;
  206. assert isCheckRoleReverted => isScheduleReverted, "Enemy was detected";
  207. }
  208. // STATUS - in progress
  209. // Ready = has waited minimum period after pending
  210. rule cooldown(method f, env e, env e2){
  211. bytes32 id;
  212. require unset(id);
  213. calldataarg args;
  214. f(e, args);
  215. // e.block.timestamp - delay > time scheduled => ready()
  216. assert e.block.timestamp >= getTimestamp(id) => ready(id, e), "No rush! When I'm ready, I'm ready";
  217. }