Skip to content
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

Adding new Superuser contract with test #952

Merged
merged 8 commits into from Jun 3, 2018

Conversation

pmosse
Copy link
Contributor

@pmosse pmosse commented May 21, 2018

Fixes #50

πŸš€ Description

I am adding a new Superuser contract. This allows a contract to have a user in the superuser role. A superuser can set a new owner for the contract, in case that the original owner address becomes compromised. The creator of the contract is the first superuser and he can then transfer his role to a different user.

  • πŸ“˜ I've reviewed the OpenZeppelin Contributor Guidelines
  • βœ… I've added tests where applicable to test my new functionality.
  • πŸ“– I've made sure that my contracts are well-documented.
  • 🎨 I've run the JS/Solidity linters and fixed any issues (npm run lint:all:fix).

* @dev A superuser can transfer his role to a new address.
*/
contract Superuser is Ownable, RBAC {
event SuperuserTransferred(address indexed previousSuperuser, address indexed newSuperuser);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These events aren't necessary. RBAC emits RoleChanged events, so SuperuserTransferred isn't needed, and Ownable already emits OwnershipTransferred.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About OwnershipTransferred: I am overriding transferOwnership and therefore it will not be emitted by Ownable.

I need to override it because in Ownable that method is onlyOwner and I need it to be onlySuperuser (actually it should be both).

I think I could do "emit super.OwnershipTransferred..." though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. the events are inherited as well, so you don't have to declare it again. just emit OwnershipTransferred(...)
  2. If you call super.transferOwnership(...) the contract would emit the event correctly regardless

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shrugs I removed the event declaration. As we discussed in Slack, I can't call super.transferOwnership because of the onlyOwner modifier.


string public constant ROLE_SUPERUSER = "superuser";

constructor () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constructor should have the public modifier

_;
}

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: formatting

/**
* @dev getter to determine if address has superuser role
*/
function superuser(address addr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's change this to isSuperuser to be more explicit.

public
{
require(newSuperuser != address(0));
emit SuperuserTransferred(msg.sender, newSuperuser);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

events not needed here, but also, generally you'll emit events after something has occurred (even though this whole process is atomic, it's good practice)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Actually I agree with that practice but I wanted to follow the pattern in Ownable.sol πŸ˜‹

* @dev Allows the current superuser to transfer his role to a newSuperuser.
* @param newSuperuser The address to transfer ownership to.
*/
function transferSuperuser(address newSuperuser)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention is to prefix arguments with _ to keep them visually separate from variables in the function body. make this _newSuperuser?

likewise for the various other arguments in this file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Same here, trying to follow the style of Ownable.sol and Whitelist.sol :)

* @dev Allows the current superuser to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlySuperuser {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just call super.transferOwnership() here instead of re-implementing the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comments at the top of the page about this. I need to override the function to make it onlySuperuser instead of onlyOwner (actually I think it should be both). Let me know your thoughts about this.

contract Superuser is Ownable, RBAC {
string public constant ROLE_SUPERUSER = "superuser";

constructor ()public {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space here

make sure to run npm run lint:sol to catch these

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shrugs Fixed. For some reason the linter is not catching it.

@shrugs shrugs requested a review from frangio May 27, 2018 20:53
@shrugs
Copy link
Contributor

shrugs commented May 28, 2018

waiting on a second review before merging πŸ‘

@pmosse
Copy link
Contributor Author

pmosse commented Jun 2, 2018

@shrugs Hey! Any updates on this? :)

@shrugs
Copy link
Contributor

shrugs commented Jun 2, 2018

Thanks for the reminder, @pmosse, I'll grab a second review by monday :)

Copy link
Contributor

@AugustoL AugustoL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@shrugs shrugs merged commit a0c03ee into OpenZeppelin:master Jun 3, 2018
@frangio
Copy link
Contributor

frangio commented Jun 4, 2018

Sorry it took me a while to get to this.

Re: transferOwnership

I need to override the function to make it onlySuperuser instead of onlyOwner (actually I think it should be both). Let me know your thoughts about this.

@pmosse I see that the contract was merged with transferOwnership as onlySuperuser. Shouldn't this be both the superuser and the owner?

@shrugs
Copy link
Contributor

shrugs commented Jun 4, 2018

@frangio I could see it both ways

With onlySuperuser, this works when the owner is also the superuser, and when the superuser changes the owner shouldn't be authorized to change themselves (it's the weakly-stored private key).

@pmosse
Copy link
Contributor Author

pmosse commented Jun 4, 2018

@shrugs Well, with the code as it is now, and assuming that the normal behaviour is to transfer the superuser role to another account as soon as the contract is deployed, we are not allowing the owner to transfer his ownership if he needs to do that. With the change proposed by @frangio, the owner will be able to transfer his ownership at any time if needed, and if the current owner's account gets compromised, the superuser can always regain control by assigning a new owner. Does that make sense?

@shrugs
Copy link
Contributor

shrugs commented Jun 4, 2018

Yeah exactly; I could see the argument for either way; neither of them are specifically good or bad; we just have to pick the "intended behavior" and stick with it.

@frangio
Copy link
Contributor

frangio commented Jun 4, 2018

Personally I'm for making it only-owner-or-superuser, because I see this as Ownable + an escape mechanism via a cold-stored key.

With onlySuperuser this is more like an "owner" role that is managed by a "superuser" role.

@shrugs
Copy link
Contributor

shrugs commented Jun 4, 2018

I support that. @pmosse ?

@pmosse
Copy link
Contributor Author

pmosse commented Jun 4, 2018

Agreed! I will start working in a PR to update this. Thanks! @shrugs @frangio

@pmosse
Copy link
Contributor Author

pmosse commented Jun 5, 2018

Created a new PR in #978 @shrugs @frangio

@pmosse pmosse deleted the feature/superuser-contract-#50 branch June 5, 2018 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Superuser: Upgradeable security for Smart Contracts
4 participants