-
Notifications
You must be signed in to change notification settings - Fork 11.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RBAC and Ownable migration towards Roles #1291
Changes from all commits
c8c2309
ed04195
5b7ec56
0530e1e
d8e7c25
a14963b
4d4a004
b2f350d
c529524
bf4a211
199e156
d4dea3c
e9cc437
436c89f
c81e75d
f6306b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
pragma solidity ^0.4.24; | ||
|
||
import "../Roles.sol"; | ||
|
||
|
||
contract CapperRole { | ||
using Roles for Roles.Role; | ||
|
||
Roles.Role private cappers; | ||
|
||
constructor() public { | ||
cappers.add(msg.sender); | ||
} | ||
|
||
modifier onlyCapper() { | ||
require(isCapper(msg.sender)); | ||
_; | ||
} | ||
|
||
function isCapper(address _account) public view returns (bool) { | ||
return cappers.has(_account); | ||
nventuro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
function addCapper(address _account) public onlyCapper { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it ok that a capper can remove other cappers? Shouldn't there be instead an admin that adds and removes cappers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's a good point; a lot of the api surface for these runs into the same issues with the problem with RBAC and it's that you can't define a public api surface by default because then changing it is super hard. and you don't know what sort of process a project might want to be able to use to be able to change the cap, for example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our rationale was that someone who has a role is already able to perform actions using that role on behalf of other people. In fact, with ownership, it was trivial to transfer ownership to a forwarder contract that would let any set of accounts use the ownership. But this could also be done informally, as an off-chain favor. Since this was already possible, we decided to make it part of the API. Otherwise it just feels like obscuring what is really possible. |
||
cappers.add(_account); | ||
} | ||
|
||
function renounceCapper() public { | ||
cappers.remove(msg.sender); | ||
} | ||
|
||
function _removeCapper(address _account) internal { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it weird that addCapper is not consistent with removeCapper. A good design principle is that everything you can do you, you will be able to undo. I guess you had a good reason to go this way, so again, just thinking out loud. We can do any changes later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We've discussed this extensively with @frangio. Our reasoning goes as follows: An account with a role should always be able to transfer it. If the account is a contract, then the conditions under which a transfer will be executed will be clear from the code. If it's an EOA, then the user already has the liberty to do whatever she wants with it, from complying to transaction requests to giving up the private keys to someone else, effectively transferring control. So, transferring can always be done. This includes transferring the role to a contract that will forward all calls from a whitelisted set of addresses, which effectively is an TL;DR: EOAs shouldn't be trusted, since people can do anything they want, if you really need control over this kind of stuff, the role-havers should also be contracts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might want a notion of a |
||
cappers.remove(_account); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
pragma solidity ^0.4.24; | ||
|
||
import "../Roles.sol"; | ||
|
||
|
||
contract MinterRole { | ||
using Roles for Roles.Role; | ||
|
||
Roles.Role private minters; | ||
|
||
constructor() public { | ||
minters.add(msg.sender); | ||
} | ||
|
||
modifier onlyMinter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like that we assign nice names to the functions. I don't like so much that the code for Minter is the same as the code for Capper. 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I probably should've gone into some more detail in the PR description: the role contracts (everything under |
||
require(isMinter(msg.sender)); | ||
_; | ||
} | ||
|
||
function isMinter(address _account) public view returns (bool) { | ||
return minters.has(_account); | ||
} | ||
|
||
function addMinter(address _account) public onlyMinter { | ||
minters.add(_account); | ||
} | ||
|
||
function renounceMinter() public { | ||
minters.remove(msg.sender); | ||
} | ||
|
||
function _removeMinter(address _account) internal { | ||
minters.remove(_account); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
pragma solidity ^0.4.24; | ||
|
||
import "../Roles.sol"; | ||
|
||
|
||
contract PauserRole { | ||
using Roles for Roles.Role; | ||
|
||
Roles.Role private pausers; | ||
|
||
constructor() public { | ||
pausers.add(msg.sender); | ||
} | ||
|
||
modifier onlyPauser() { | ||
require(isPauser(msg.sender)); | ||
_; | ||
} | ||
|
||
function isPauser(address _account) public view returns (bool) { | ||
return pausers.has(_account); | ||
} | ||
|
||
function addPauser(address _account) public onlyPauser { | ||
pausers.add(_account); | ||
} | ||
|
||
function renouncePauser() public { | ||
pausers.remove(msg.sender); | ||
} | ||
|
||
function _removePauser(address _account) internal { | ||
pausers.remove(_account); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm looking at you Venturo! 🙄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean D: