AccessControl.spec 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import "helpers/helpers.spec"
  2. import "methods/IAccessControl.spec"
  3. /*
  4. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  5. │ Definitions │
  6. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  7. */
  8. definition DEFAULT_ADMIN_ROLE() returns bytes32 = 0x0000000000000000000000000000000000000000000000000000000000000000;
  9. /*
  10. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  11. │ Identify entrypoints: only grantRole, revokeRole and renounceRole can alter permissions │
  12. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  13. */
  14. rule onlyGrantCanGrant(env e, method f, bytes32 role, address account) {
  15. calldataarg args;
  16. bool hasRoleBefore = hasRole(role, account);
  17. f(e, args);
  18. bool hasRoleAfter = hasRole(role, account);
  19. assert (
  20. !hasRoleBefore &&
  21. hasRoleAfter
  22. ) => (
  23. f.selector == grantRole(bytes32, address).selector
  24. );
  25. assert (
  26. hasRoleBefore &&
  27. !hasRoleAfter
  28. ) => (
  29. f.selector == revokeRole(bytes32, address).selector ||
  30. f.selector == renounceRole(bytes32, address).selector
  31. );
  32. }
  33. /*
  34. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  35. │ Function correctness: grantRole only affects the specified user/role combo │
  36. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  37. */
  38. rule grantRoleEffect(env e, bytes32 role) {
  39. require nonpayable(e);
  40. bytes32 otherRole;
  41. address account;
  42. address otherAccount;
  43. bool isCallerAdmin = hasRole(getRoleAdmin(role), e.msg.sender);
  44. bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
  45. grantRole@withrevert(e, role, account);
  46. bool success = !lastReverted;
  47. bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
  48. // liveness
  49. assert success <=> isCallerAdmin;
  50. // effect
  51. assert success => hasRole(role, account);
  52. // no side effect
  53. assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount);
  54. }
  55. /*
  56. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  57. │ Function correctness: revokeRole only affects the specified user/role combo │
  58. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  59. */
  60. rule revokeRoleEffect(env e, bytes32 role) {
  61. require nonpayable(e);
  62. bytes32 otherRole;
  63. address account;
  64. address otherAccount;
  65. bool isCallerAdmin = hasRole(getRoleAdmin(role), e.msg.sender);
  66. bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
  67. revokeRole@withrevert(e, role, account);
  68. bool success = !lastReverted;
  69. bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
  70. // liveness
  71. assert success <=> isCallerAdmin;
  72. // effect
  73. assert success => !hasRole(role, account);
  74. // no side effect
  75. assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount);
  76. }
  77. /*
  78. ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  79. │ Function correctness: renounceRole only affects the specified user/role combo │
  80. └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
  81. */
  82. rule renounceRoleEffect(env e, bytes32 role) {
  83. require nonpayable(e);
  84. bytes32 otherRole;
  85. address account;
  86. address otherAccount;
  87. bool hasOtherRoleBefore = hasRole(otherRole, otherAccount);
  88. renounceRole@withrevert(e, role, account);
  89. bool success = !lastReverted;
  90. bool hasOtherRoleAfter = hasRole(otherRole, otherAccount);
  91. // liveness
  92. assert success <=> account == e.msg.sender;
  93. // effect
  94. assert success => !hasRole(role, account);
  95. // no side effect
  96. assert hasOtherRoleBefore != hasOtherRoleAfter => (role == otherRole && account == otherAccount);
  97. }