Proposal to revamp Roles
See original GitHub issueRBAC
was removed after https://github.com/OpenZeppelin/openzeppelin-solidity/issues/1090 due to issues with having strings be keys in the mapping, and replaces with Roles
in https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1291. Integer ids were considered, but ultimately discarded, partly because of a lack of an id allocation mechanism (hash of strings?).
The new scheme works, but it has a couple wrinkles. Each new role requires the creation of a new role contract, which will be almost a carbon copy of all other roles. Additionally, they all add their own functions, polluting the contract’s ABI and leading to duplicated bytecode. We’ve considered autogenerating these contracts (https://github.com/OpenZeppelin/openzeppelin-solidity/issues/1290), but that requires new tooling, documentation, a pre-compile step, etc., all of which are best avoided. Finally, role reuse may lead to unexpected situations (e.g. both ERC20Mintable
and ERC721Mintable
use the same MinterRole
).
I propose an alternative scheme, where we opt for an approach similar to RBAC
’s (although I’d propose a more friendly name, perhaps RoleChecker
?), but get rid of the id issue altogether by using automatically generated ids.
contract RoleChecker {
mapping (uint256 => Roles.Role) roles;
Counters.Counter counter;
function hasRole(uint256 id) view returns (bool) { return roles[id]; }
function newRole() returns (uint256) {
counter.increment();
return keccak(address(this), counter.current());
}
}
Each contract that requires roles simply inherits from RoleChecker
and creates whichever roles it needs.
contract ERC20Mintable is RoleChecker {
uint256 _erc20mintRoleId;
constructor() {
_erc20mintRoleId = newRole();
}
function mint(...) onlyRole(_erc20mintRoleId) {
...
}
function erc20mintRoleId() view returns(uint256) {
return _erc20mintRoleId;
}
}
The only added boilerplate is a public getter for this id, so that users can retrieve it and use it to e.g. call addRole(id)
, hasRole(id, account)
, etc.
And since each role id is created with a hash of an integer (autoincremented by Counter
) and the contract’s address, they will be unique for each contract. Preventing these clashes will reduce user error, where someone may mistakenly use a different contract’s role ids.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:3
- Comments:5 (5 by maintainers)
Hi @nventuro @frangio I will take a deeper look into this and revert with questions.
With the migration to Solidity v0.6 arriving soon, we will need to tackle this issue as part of the upcoming v3.0 release.
Since there are still multiple ideas out there, I created Redesigning Access Control on our forum to gather feedback about the different proposals, and settle on a high-level design we’re comfortable with. Once we get to that point, we can continue work here.
Please participate in this process by sharing your ideas and experience, so we can design the best solution possible!