If you check this link: openzeppelin github access control you will notice they use 2 function for granting a role:
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
This function is external. All what it does it calling the internal function _grantRole
. Note they add the modifier onlyRole
which means if you dont have the right permissions (role), then the call will fail.
However, this is the internal function:
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
note that the internal function does not have the modifier onlyRole
which means it does not do permission checking. As an internal function, I can write a contract and inherit this contract from openzeppelin and since my contract is derived contract, I have access to the internal functions, and I can easily write a function that call the internal function "_grantRole". Why that wont work? I dont understand the security behind this since only the external functions check for the role, but the internal ones dont.
Any contract can inherit this and call the internal functions. Would someone please explain!