Ownable2Step.spec 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import "helpers.spec"
  2. import "methods/IOwnable2Step.spec"
  3. methods {
  4. restricted()
  5. }
  6. /*
  7. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  8. │ Function correctness: transferOwnership sets the pending owner │
  9. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  10. */
  11. rule transferOwnership(env e) {
  12. require nonpayable(e);
  13. address newOwner;
  14. address current = owner();
  15. transferOwnership@withrevert(e, newOwner);
  16. bool success = !lastReverted;
  17. assert success <=> e.msg.sender == current, "unauthorized caller";
  18. assert success => pendingOwner() == newOwner, "pending owner not set";
  19. assert success => owner() == current, "current owner changed";
  20. }
  21. /*
  22. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  23. │ Function correctness: renounceOwnership removes the owner and the pendingOwner │
  24. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  25. */
  26. rule renounceOwnership(env e) {
  27. require nonpayable(e);
  28. address current = owner();
  29. renounceOwnership@withrevert(e);
  30. bool success = !lastReverted;
  31. assert success <=> e.msg.sender == current, "unauthorized caller";
  32. assert success => pendingOwner() == 0, "pending owner not cleared";
  33. assert success => owner() == 0, "owner not cleared";
  34. }
  35. /*
  36. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  37. │ Function correctness: acceptOwnership changes owner and reset pending owner │
  38. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  39. */
  40. rule acceptOwnership(env e) {
  41. require nonpayable(e);
  42. address current = owner();
  43. address pending = pendingOwner();
  44. acceptOwnership@withrevert(e);
  45. bool success = !lastReverted;
  46. assert success <=> e.msg.sender == pending, "unauthorized caller";
  47. assert success => pendingOwner() == 0, "pending owner not cleared";
  48. assert success => owner() == pending, "owner not transferred";
  49. }
  50. /*
  51. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  52. │ Access control: only current owner can call restricted functions │
  53. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  54. */
  55. rule onlyCurrentOwnerCanCallOnlyOwner(env e) {
  56. require nonpayable(e);
  57. address current = owner();
  58. calldataarg args;
  59. restricted@withrevert(e, args);
  60. assert !lastReverted <=> e.msg.sender == current, "access control failed";
  61. }
  62. /*
  63. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  64. │ Rule: ownership and pending ownership can only change in specific ways │
  65. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  66. */
  67. rule ownerOrPendingOwnerChange(env e, method f) {
  68. address oldCurrent = owner();
  69. address oldPending = pendingOwner();
  70. calldataarg args;
  71. f(e, args);
  72. address newCurrent = owner();
  73. address newPending = pendingOwner();
  74. // If owner changes, must be either acceptOwnership or renounceOwnership
  75. assert oldCurrent != newCurrent => (
  76. (e.msg.sender == oldPending && newCurrent == oldPending && newPending == 0 && f.selector == acceptOwnership().selector) ||
  77. (e.msg.sender == oldCurrent && newCurrent == 0 && newPending == 0 && f.selector == renounceOwnership().selector)
  78. );
  79. // If pending changes, must be either acceptance or reset
  80. assert oldPending != newPending => (
  81. (e.msg.sender == oldCurrent && newCurrent == oldCurrent && f.selector == transferOwnership(address).selector) ||
  82. (e.msg.sender == oldPending && newCurrent == oldPending && newPending == 0 && f.selector == acceptOwnership().selector) ||
  83. (e.msg.sender == oldCurrent && newCurrent == 0 && newPending == 0 && f.selector == renounceOwnership().selector)
  84. );
  85. }