AccessControlEnumerable.sol 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "./IAccessControlEnumerable.sol";
  4. import "./AccessControl.sol";
  5. import "../utils/structs/EnumerableSet.sol";
  6. /**
  7. * @dev Extension of {AccessControl} that allows enumerating the members of each role.
  8. */
  9. abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
  10. using EnumerableSet for EnumerableSet.AddressSet;
  11. mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;
  12. /**
  13. * @dev See {IERC165-supportsInterface}.
  14. */
  15. function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
  16. return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
  17. }
  18. /**
  19. * @dev Returns one of the accounts that have `role`. `index` must be a
  20. * value between 0 and {getRoleMemberCount}, non-inclusive.
  21. *
  22. * Role bearers are not sorted in any particular way, and their ordering may
  23. * change at any point.
  24. *
  25. * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
  26. * you perform all queries on the same block. See the following
  27. * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
  28. * for more information.
  29. */
  30. function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
  31. return _roleMembers[role].at(index);
  32. }
  33. /**
  34. * @dev Returns the number of accounts that have `role`. Can be used
  35. * together with {getRoleMember} to enumerate all bearers of a role.
  36. */
  37. function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
  38. return _roleMembers[role].length();
  39. }
  40. /**
  41. * @dev Overload {grantRole} to track enumerable memberships
  42. */
  43. function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
  44. super.grantRole(role, account);
  45. _roleMembers[role].add(account);
  46. }
  47. /**
  48. * @dev Overload {revokeRole} to track enumerable memberships
  49. */
  50. function revokeRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
  51. super.revokeRole(role, account);
  52. _roleMembers[role].remove(account);
  53. }
  54. /**
  55. * @dev Overload {renounceRole} to track enumerable memberships
  56. */
  57. function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {
  58. super.renounceRole(role, account);
  59. _roleMembers[role].remove(account);
  60. }
  61. /**
  62. * @dev Overload {_setupRole} to track enumerable memberships
  63. */
  64. function _setupRole(bytes32 role, address account) internal virtual override {
  65. super._setupRole(role, account);
  66. _roleMembers[role].add(account);
  67. }
  68. }