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; assert checkRevert => grantRevert, "modifier goes bananas"; } // STATUS - verified // check onlyRole modifier for revokeRole() rule onlyRoleModifierCheckRevoke(env e){ bytes32 role; address account; _checkRole@withrevert(e, getRoleAdmin(role)); bool checkRevert = lastReverted; revokeRole@withrevert(e, role, account); bool revokeRevert = lastReverted; assert checkRevert => revokeRevert, "modifier goes bananas"; } // 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); grantRole(e, role, account); bool hasRoleAfter = hasRole(anotherRole, nonEffectedAcc); assert hasRoleBefore == hasRoleAfter, "modifier goes bananas"; } // 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); assert hasRoleBefore == hasRoleAfter, "modifier goes bananas"; }