Add ERC165 interface detection to AccessControl (#2562)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
(cherry picked from commit 29ffe6f426)
This commit is contained in:
Francisco Giordano
2021-03-04 18:50:12 -03:00
parent 69ca2ad676
commit f07c39be8a
9 changed files with 78 additions and 11 deletions

View File

@ -3,6 +3,18 @@
pragma solidity ^0.8.0;
import "../utils/Context.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
/**
* @dev Contract module that allows children to implement role-based access
@ -42,7 +54,7 @@ import "../utils/Context.sol";
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context {
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping (address => bool) members;
bytes32 adminRole;
@ -79,10 +91,18 @@ abstract contract AccessControl is Context {
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view returns (bool) {
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
@ -92,7 +112,7 @@ abstract contract AccessControl is Context {
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
@ -106,7 +126,7 @@ abstract contract AccessControl is Context {
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
function grantRole(bytes32 role, address account) public virtual override {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
@ -121,7 +141,7 @@ abstract contract AccessControl is Context {
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
function revokeRole(bytes32 role, address account) public virtual override {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
@ -141,7 +161,7 @@ abstract contract AccessControl is Context {
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual {
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);