pragma solidity ^0.6.0; import "../utils/EnumerableSet.sol"; import "../GSN/Context.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, _msgSender())); * ... * } * ``` * * Roles can be granted and revoked programatically by calling the `internal` * {_grantRole} and {_revokeRole} functions. * * This can also be achieved dynamically via the `external` {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRoke}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. */ abstract contract AccessControl is Context { using EnumerableSet for EnumerableSet.AddressSet; struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; } mapping (bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call: * - if using `grantRole`, it is the admin role bearer * - if using `_grantRole`, its meaning is system-dependent */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) * - if using `_renounceRole`, its meaning is system-dependent */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view returns (bool) { return _roles[role].members.contains(account); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view returns (uint256) { return _roles[role].members.length(); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view returns (address) { return _roles[role].members.get(index); } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * Calls {_grantRole} internally. * * Requirements: * * - the caller must have `role`'s admin role. */ function grantRole(bytes32 role, address account) external virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant"); _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * Calls {_revokeRole} internally. * * Requirements: * * - the caller must have `role`'s admin role. */ function revokeRole(bytes32 role, address account) external virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke"); _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external virtual { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. */ function _grantRole(bytes32 role, address account) internal virtual { if (_roles[role].members.add(account)) { emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (_roles[role].members.remove(account)) { emit RoleRevoked(role, account, _msgSender()); } } /** * @dev Sets `adminRole` as `role`'s admin role. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { _roles[role].adminRole = adminRole; } }