parent
f21f86c3c1
commit
6c4ffe783f
@ -1,85 +1,133 @@ |
||||
methods { |
||||
grantRole(bytes32, address) |
||||
revokeRole(bytes32, address) |
||||
_checkRole(bytes32) |
||||
safeTransferFrom(address, address, uint256, uint256, bytes) |
||||
safeBatchTransferFrom(address, address, uint256[], uint256[], bytes) |
||||
|
||||
getRoleAdmin(bytes32) returns(bytes32) envfree |
||||
hasRole(bytes32, address) returns(bool) envfree |
||||
} |
||||
|
||||
|
||||
// STATUS - verified |
||||
// If `onlyRole` modifier reverts then `grantRole()` reverts |
||||
rule onlyRoleModifierCheckGrant(env e){ |
||||
bytes32 role; address account; |
||||
|
||||
_checkRole@withrevert(e, getRoleAdmin(role)); |
||||
bool checkRevert = lastReverted; |
||||
|
||||
grantRole@withrevert(e, role, account); |
||||
bool grantRevert = lastReverted; |
||||
getRoleAdmin(bytes32) returns(bytes32) envfree |
||||
|
||||
assert checkRevert => grantRevert, "modifier goes bananas"; |
||||
grantRole(bytes32, address) |
||||
revokeRole(bytes32, address) |
||||
renounceRole(bytes32, address) |
||||
} |
||||
|
||||
|
||||
// STATUS - verified |
||||
// check onlyRole modifier for revokeRole() |
||||
rule onlyRoleModifierCheckRevoke(env e){ |
||||
bytes32 role; address account; |
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: only grantRole can grant a role │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule onlyGrantCanGrant(env e, bytes32 role, address account) { |
||||
require !hasRole(role, account); |
||||
|
||||
_checkRole@withrevert(e, getRoleAdmin(role)); |
||||
bool checkRevert = lastReverted; |
||||
method f; calldataarg args; |
||||
f(e, args); |
||||
|
||||
revokeRole@withrevert(e, role, account); |
||||
bool revokeRevert = lastReverted; |
||||
|
||||
assert checkRevert => revokeRevert, "modifier goes bananas"; |
||||
assert hasRole(role, account) => f.selector == grantRole(bytes32, address).selector; |
||||
} |
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: only revokeRole and renounceRole can grant a role │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule onlyRevokeAndRenounceCanRevoke(env e, bytes32 role, address account) { |
||||
require hasRole(role, account); |
||||
|
||||
// STATUS - verified |
||||
// grantRole() does not affect another accounts |
||||
rule grantRoleEffect(env e){ |
||||
bytes32 role; address account; |
||||
bytes32 anotherRole; address nonEffectedAcc; |
||||
require account != nonEffectedAcc; |
||||
|
||||
bool hasRoleBefore = hasRole(anotherRole, nonEffectedAcc); |
||||
method f; calldataarg args; |
||||
f(e, args); |
||||
|
||||
grantRole(e, role, account); |
||||
|
||||
bool hasRoleAfter = hasRole(anotherRole, nonEffectedAcc); |
||||
|
||||
assert hasRoleBefore == hasRoleAfter, "modifier goes bananas"; |
||||
assert !hasRole(role, account) => (f.selector == revokeRole(bytes32, address).selector || f.selector == renounceRole(bytes32, address).selector); |
||||
} |
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: only an account with admin role can call grantRole │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule onlyAdminCanGrant(env e, bytes32 role, address account) { |
||||
bool isAdmin = hasRole(getRoleAdmin(role), e.msg.sender); |
||||
|
||||
// STATUS - verified |
||||
// revokeRole() does not affect another accounts |
||||
rule revokeRoleEffect(env e){ |
||||
bytes32 role; address account; |
||||
bytes32 anotherRole; address nonEffectedAcc; |
||||
require account != nonEffectedAcc; |
||||
|
||||
bool hasRoleBefore = hasRole(anotherRole, nonEffectedAcc); |
||||
|
||||
revokeRole(e, role, account); |
||||
|
||||
bool hasRoleAfter = hasRole(anotherRole, nonEffectedAcc); |
||||
grantRole@withrevert(e, role, account); |
||||
|
||||
assert hasRoleBefore == hasRoleAfter, "modifier goes bananas"; |
||||
assert !lastReverted => isAdmin; |
||||
} |
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: only an account with admin role can call revokeRole │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule onlyAdminCanRevoke(env e, bytes32 role, address account) { |
||||
bool isAdmin = hasRole(getRoleAdmin(role), e.msg.sender); |
||||
|
||||
revokeRole@withrevert(e, role, account); |
||||
|
||||
assert !lastReverted => isAdmin; |
||||
} |
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: only the affected account can revoke │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule onlyUserCanRenounce(env e, bytes32 role, address account) { |
||||
renounceRole@withrevert(e, role, account); |
||||
assert !lastReverted => account == e.msg.sender; |
||||
} |
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: grantRole only affects the specified user/role combo │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule grantRoleEffect(env e) { |
||||
bytes32 role1; bytes32 role2; |
||||
address account1; address account2; |
||||
|
||||
bool hasRoleBefore = hasRole(role1, account1); |
||||
grantRole(e, role2, account2); |
||||
bool hasRoleAfter = hasRole(role1, account1); |
||||
|
||||
assert ( |
||||
hasRoleBefore != hasRoleAfter |
||||
) => ( |
||||
hasRoleAfter == true && role1 == role2 && account1 == account2 |
||||
); |
||||
} |
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: revokeRole only affects the specified user/role combo │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule revokeRoleEffect(env e) { |
||||
bytes32 role1; bytes32 role2; |
||||
address account1; address account2; |
||||
|
||||
bool hasRoleBefore = hasRole(role1, account1); |
||||
revokeRole(e, role2, account2); |
||||
bool hasRoleAfter = hasRole(role1, account1); |
||||
|
||||
assert ( |
||||
hasRoleBefore != hasRoleAfter |
||||
) => ( |
||||
hasRoleAfter == false && role1 == role2 && account1 == account2 |
||||
); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* |
||||
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
||||
│ Rule: renounceRole only affects the specified user/role combo │ |
||||
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
||||
*/ |
||||
rule renounceRoleEffect(env e) { |
||||
bytes32 role1; bytes32 role2; |
||||
address account1; address account2; |
||||
|
||||
bool hasRoleBefore = hasRole(role1, account1); |
||||
renounceRole(e, role2, account2); |
||||
bool hasRoleAfter = hasRole(role1, account1); |
||||
|
||||
assert ( |
||||
hasRoleBefore != hasRoleAfter |
||||
) => ( |
||||
hasRoleAfter == false && role1 == role2 && account1 == account2 |
||||
); |
||||
} |
Loading…
Reference in new issue