Thanks everyone for your feedback and suggestions! They have been super valuable in evaluating this complex topic.
I am now leaning towards the following idea, inspired by @albertocuestacanada’s proposals, incorporating @Austin-Williams and @frangio’s comments about authorization vs identification, and @MicahZoltu and @abcoathup’s notes about enumerability and a safe API.
@jonathan’s comment about permissions vs roles is also very interesting, though I think such a system might be better codified at the user level instead of at the library level (e.g. by having action X require that the user has either role A or B,).
The proposed solution attempts to provide flexibility while keeping usage simple for simple scenarios:
- Roles cannot be tranferred
- Each role has an associated admin role, and a role can only be granted or revoked by accounts that have it’s admin role
-
DEFAULT_ADMIN_ROLEis the default admin role for all roles - A role’s admin role can be changed via an
internalfunction - The external API is kept minimal: contract’s that use
AccessControlonly add anexternal puregetter for each newly defined role
It does not:
- Separate
grantandrevokeconcerns: a role’s admin can perform both tasks. I haven’t found scenarios in which this distinction is important.
For improved readability, I split the interface from the code:
-
IAccessControlholds the entireexternalAPI -
AccessControlhas the implementation, plus theinternalfunctions_grantRoleand _revokeRole. I removedRoles.solhere and replaced it with usage ofEnumerableSet -
ERC20Flavorsshows usage examples for different system configurations
The great thing about this is that the default admin role lets us greatly simplify how the library is used, opting-in to complexity as the system grows more sophisticated (see the snippets in ERC20Flavors).
It can also be easily used as a standalone contract queried by many other contracts in a system (as suggested by @albertocuestacanada) by simply inheriting from it, setting up initial roles in a constructor and exposing _setRoleAdmin externally. We might provide such a contract in the library.
I’d love to hear your thoughts on the matter! I’ll be offline on vacation for a couple weeks, but plan to wrap this up and include it on the v3.0 release by mid-March. While I’m gone, @frangio will reply to questions as my sidekick in Contracts. Thanks again to everyone for participating in the process!