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

RBAC and Ownable migration towards Roles #1291

Merged
merged 16 commits into from
Sep 7, 2018
Merged

RBAC and Ownable migration towards Roles #1291

merged 16 commits into from
Sep 7, 2018

Conversation

nventuro
Copy link
Contributor

@nventuro nventuro commented Sep 6, 2018

Notable changes:

  • Ownable is no longer used (except in drafts)
  • RBAC has been removed
  • Secondary was introduced to replace Ownable in simple cases (e.g. Escrow)
  • The Roles library is now much more widely used, though the role contracts themselves have to be manually generated (see Automatically generate Role contracts #1290)

Closes #366
Closes #1090
Closes #1146

nventuro and others added 12 commits August 22, 2018 18:47
* Moved RBAC tests to access.

* Added Roles.addMany and tests.

* Fixed linter error.

* Now using uint256 indexes.
* Deleted RBACCappedTokenMock.

* Removed RBACMintableToken.

* Removed RBACMintableToken from the MintedCrowdsale tests.
* Roles can now be transfered.

* Now explicitly checking support for the null address.

* Now rejecting transfer to a role-haver.

* Added renounce, roles can no longer be transfered to 0.

* Fixed linter errors.

* Fixed a Roles test.
* Added barebones Secondary.

* Added transferPrimary

* Escrow is now Secondary instead of Ownable.

* Now reverting on transfers to 0.

* The Secondary's primary is now private.
* Minor test style improvements (#1219)

* Changed .eq to .equal

* Changed equal(bool) to .to.be.bool

* Changed be.bool to equal(bool), disallowed unused expressions.

* Add ERC165Query library (#1086)

* Add ERC165Query library

* Address PR Comments

* Add tests and mocks from #1024 and refactor code slightly

* Fix javascript and solidity linting errors

* Split supportsInterface into three methods as discussed in #1086

* Change InterfaceId_ERC165 comment to match style in the rest of the repo

* Fix max-len lint issue on ERC165Checker.sol

* Conditionally ignore the asserts during solidity-coverage test

* Switch to abi.encodeWithSelector and add test for account addresses

* Switch to supportsInterfaces API as suggested by @frangio

* Adding ERC165InterfacesSupported.sol

* Fix style issues

* Add test for supportsInterfaces returning false

* Add ERC165Checker.sol newline

* feat: fix coverage implementation

* fix: solidity linting error

* fix: revert to using boolean tests instead of require statements

* fix: make supportsERC165Interface private again

* rename SupportsInterfaceWithLookupMock to avoid name clashing

* Added mint and burn tests for zero amounts. (#1230)

* Changed .eq to .equal. (#1231)

* ERC721 pausable token (#1154)

* ERC721 pausable token

* Reuse of ERC721 Basic behavior for Pausable, split view checks in paused state & style fixes

* [~] paused token behavior

* Add some detail to releasing steps (#1190)

* add note about pulling upstream changes to release branch

* add comment about upstream changes in merging section

* Increase test coverage (#1237)

* Fixed a SplitPayment test

* Deleted unnecessary function.

* Improved PostDeliveryCrowdsale tests.

* Improved RefundableCrowdsale tests.

* Improved MintedCrowdsale tests.

* Improved IncreasingPriceCrowdsale tests.

* Fixed a CappedCrowdsale test.

* Improved TimedCrowdsale tests.

* Improved descriptions of added tests.

*  ci: trigger docs update on tag  (#1186)

* MintableToken now uses Roles.

* Fixed FinalizableCrowdsale test.

* Roles can now be transfered.

* Fixed tests related to MintableToken.

* Removed Roles.check.

* Renamed transferMintPermission.

* Moved MinterRole

* Fixed RBAC.

* Adressed review comments.

* Addressed review comments

* Fixed linter errors.

* Added Events tests of Pausable contract (#1207)

* Fixed roles tests.

* Rename events to past-tense (#1181)

* fix: refactor sign.js and related tests (#1243)

* fix: refactor sign.js and related tests

* fix: remove unused dep

* fix: update package.json correctly

* Added "_" sufix to internal variables (#1171)

* Added PublicRole test.

* Fixed crowdsale tests.

* Rename ERC interfaces to I prefix (#1252)

* rename ERC20 to IERC20

* move ERC20.sol to IERC20.sol

* rename StandardToken to ERC20

* rename StandardTokenMock to ERC20Mock

* move StandardToken.sol to ERC20.sol, likewise test and mock files

* rename MintableToken to ERC20Mintable

* move MintableToken.sol to ERC20Mintable.sol, likewise test and mock files

* rename BurnableToken to ERC20Burnable

* move BurnableToken.sol to ERC20Burnable.sol, likewise for related files

* rename CappedToken to ERC20Capped

* move CappedToken.sol to ERC20Capped.sol, likewise for related files

* rename PausableToken to ERC20Pausable

* move PausableToken.sol to ERC20Pausable.sol, likewise for related files

* rename DetailedERC20 to ERC20Detailed

* move DetailedERC20.sol to ERC20Detailed.sol, likewise for related files

* rename ERC721 to IERC721, and likewise for other related interfaces

* move ERC721.sol to IERC721.sol, likewise for other 721 interfaces

* rename ERC721Token to ERC721

* move ERC721Token.sol to ERC721.sol, likewise for related files

* rename ERC721BasicToken to ERC721Basic

* move ERC721BasicToken.sol to ERC721Basic.sol, likewise for related files

* rename ERC721PausableToken to ERC721Pausable

* move ERC721PausableToken.sol to ERC721Pausable.sol

* rename ERC165 to IERC165

* move ERC165.sol to IERC165.sol

* amend comment that ERC20 is based on FirstBlood

* fix comments mentioning IERC721Receiver

* added explicit visibility (#1261)

* Remove underscores from event parameters. (#1258)

* Remove underscores from event parameters.

Fixes #1175

* Add comment about ERC

* Move contracts to subdirectories (#1253)

* Move contracts to subdirectories

Fixes #1177.

This Change also removes the LimitBalance contract.

* fix import

* move MerkleProof to cryptography

* Fix import

* Remove HasNoEther, HasNoTokens, HasNoContracts, and NoOwner (#1254)

* remove HasNoEther, HasNoTokens, HasNoContracts, and NoOwner

* remove unused ERC223TokenMock

* remove Contactable

* remove TokenDestructible

* remove DeprecatedERC721

* inline Destructible#destroy in Bounty

* remove Destructible

* Functions in interfaces changed to "external" (#1263)

* Add a leading underscore to internal and private functions. (#1257)

* Add a leading underscore to internal and private functions.

Fixes #1176

* Remove super

* update the ERC721 changes

* add missing underscore after merge

* Fix mock

* Improve encapsulation on SignatureBouncer, Whitelist and RBAC example (#1265)

* Improve encapsulation on Whitelist

* remove only

* update whitelisted crowdsale test

* Improve encapsulation on SignatureBouncer

* fix missing test

* Improve encapsulation on RBAC example

* Improve encapsulation on RBAC example

* Remove extra visibility

* Improve encapsulation on ERC20 Mintable

* Improve encapsulation on Superuser

* fix lint

* add missing constant

* Addressed review comments.

* Fixed build error.
* Improved Roles API.

* fix linter error
* remove Claimable, DelayedClaimable, Heritable

* remove SimpleSavingsWallet example which used Heritable

(cherry picked from commit 0dc7117)
* Added role tests.

* Added PauserRole tests to contracts that have that role.

* Added MinterRole tests to contracts that have that role.

* Fixed linter errors.
* Added CapperRole.

* RefundEscrow is now Secondary.

* FinalizableCrowdsale is no longer Ownable.

* Removed Whitelist and WhitelistedCrowdsale, redesign needed.

* Fixed linter errors, disabled lbrace due to it being buggy.
* Added CapperRole.

* RefundEscrow is now Secondary.

* FinalizableCrowdsale is no longer Ownable.

* Removed Whitelist and WhitelistedCrowdsale, redesign needed.

* Fixed linter errors, disabled lbrace due to it being buggy.

* Moved SignatureBouncer tests.

* Deleted RBAC and Superuser.

* Deleted rbac directory.

* Updated readme.

* SignatureBouncer now uses SignerRole, renamed bouncer to signer.
@nventuro nventuro added feature New contracts, functions, or helpers. kind:improvement tests Test suite and helpers. contracts Smart contract code. breaking change Changes that break backwards compatibility of the public API. labels Sep 6, 2018
@nventuro nventuro added this to the v2.0 milestone Sep 6, 2018
@nventuro nventuro self-assigned this Sep 6, 2018
@frangio frangio added the on hold Put on hold for some reason that must be specified in a comment. label Sep 6, 2018
@frangio
Copy link
Contributor

frangio commented Sep 6, 2018

On hold for #1276.

* feat: implement ERC721Mintable and ERC721Burnable

* fix: linting errors

* fix: remove unused mintable mock for ERC721BasicMock

* fix: add finishMinting tests

* fix: catch MintFinished typo

* inline ERC721Full behavior

* undo pretty formatting

* fix lint errors

* rename canMint to onlyBeforeMintingFinished for consistency with ERC20Mintable
@frangio frangio removed the on hold Put on hold for some reason that must be specified in a comment. label Sep 6, 2018
shrugs
shrugs previously approved these changes Sep 6, 2018
return finalized_;
}

/**
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() public onlyOwner {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

come-maiz
come-maiz previously approved these changes Sep 7, 2018
Copy link
Contributor

@come-maiz come-maiz left a comment

Choose a reason for hiding this comment

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

Ok, in here I just have $opinions that we can discuss later, maybe with beers when we meet :)
My only complaints are about things that are back to public, I will prepare a PR for this so you review it tomorrow.

@@ -15,32 +13,17 @@ library Roles {
/**
* @dev give an account access to this role
*/
function add(Role storage _role, address _account)
internal
{
Copy link
Contributor

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! 🙄

Copy link
Contributor Author

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:

contracts/access/Roles.sol Show resolved Hide resolved
contracts/access/roles/CapperRole.sol Show resolved Hide resolved
cappers.remove(msg.sender);
}

function _removeCapper(address _account) internal {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 add to multiple addresses. We decided to formalize this mechanism, and simply remove transfer and make add public by default. Note that remove plays no part here: at no point does having a role give you the power to take it away from someone else, but it does let you act at someone else's behest.

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

We might want a notion of a public remove function but we will wait and see what use-cases come up to add later. :)

return cappers.has(_account);
}

function addCapper(address _account) public onlyCapper {
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

minters.add(msg.sender);
}

modifier onlyMinter() {
Copy link
Contributor

Choose a reason for hiding this comment

The 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. 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 access/roles/, and associated tests) will be auto-generated in the future (see #1290), since they are all identical (we call it the 'role boilerplate'). This is sort of a limitation of how libraries work in Solidty, but I'm not yet convinced what'd be the best way to tackle this moving forward. For now, code repetition is what we have.

uint8 private decimals_;
string public name;
string public symbol;
uint8 public decimals;
Copy link
Contributor

Choose a reason for hiding this comment

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

hey, what happened here? I suppose this was a failed merge.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this needs to be merged into the new master again? not sure

Copy link
Contributor

Choose a reason for hiding this comment

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

We must've merged this file wrong.

event Minted(address indexed to, uint256 tokenId);
event MintingFinished();

bool public mintingFinished = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

public? Nooo

Copy link
Contributor

Choose a reason for hiding this comment

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

good point; if we update this, also update the ERC20Mintable that this was copy/pasted from

@come-maiz come-maiz dismissed stale reviews from shrugs and themself via 436c89f September 7, 2018 05:07
Copy link
Contributor

@frangio frangio left a comment

Choose a reason for hiding this comment

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

:shipit:

Copy link
Contributor

@come-maiz come-maiz left a comment

Choose a reason for hiding this comment

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

:shipit:

@nventuro
Copy link
Contributor Author

nventuro commented Sep 7, 2018

Thanks for the thorough review @ElOpio @shrugs @frangio 🎉

@nventuro nventuro merged commit f12817e into master Sep 7, 2018
@nventuro nventuro deleted the rbac-migration branch September 7, 2018 10:16
@mjdietzx
Copy link

mjdietzx commented Sep 9, 2018

Just to be clear, the recommended way to implement Whitelist functionality after this change is to do something like:

Just so I can understand, why did you decide to remove the whitelist and whitelisted crowd-sale? Was it just not adding core functionality / unnecessary? Or is there some deeper reason?

@nventuro
Copy link
Contributor Author

nventuro commented Sep 9, 2018

Hey @mjdietzx! There's a short explanation here: the gist of it is that, if implemented using the current role system, the whitelistees would also become whitelisters themselves. This may or may not be an issue: we need to figure out what our purpose is with those contracts, and them implement them. Since 2.0 now features a stable API, I didn't want to include a contract we weren't 100% sure about.

@mjdietzx
Copy link

Hey @nventuro, thanks for the response! Just some feedback, I think Whitelist.sol and whitelisted crowd-sales in general are a very common use-case (kyc & aml keep getting stricter 😕) And a whitelisted address being able to add another address to the whitelist wouldn't be acceptable for this use-case. So I would think it's important to be able to implement this well in openzeppelin.

Either way, we'll be updating to v2.0 (looking forward to it) and will find a good solution for our whitelist with whatever you decide to go with. Looking forward to the release, thanks!

@frangio
Copy link
Contributor

frangio commented Sep 10, 2018

@mjdietzx Please check out my comment in #1292 and let us know what you think over there!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change Changes that break backwards compatibility of the public API. contracts Smart contract code. feature New contracts, functions, or helpers. tests Test suite and helpers.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants