AccessControlEnumerable.sol 2.6 KB

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