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

Fix/whitelisted crowdsale #981

Merged
merged 7 commits into from
Jun 15, 2018

Conversation

shrugs
Copy link
Contributor

@shrugs shrugs commented Jun 6, 2018

🚀 Description

found the issue! truffle-contract's send() function is bad software and doesn't accept an options hash like every other method in the library, so the sender of that transaction is always the default account, which is not authorized and therefore fails the whitelist check.

I also took this opportunity to refactor WhitelistedCrowdsale, Whitelist.sol, and RBAC.sol to get them up to date with various best practices since they were made.

  • 📘 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).

@shrugs shrugs requested a review from come-maiz June 6, 2018 23:14
import "../../ownership/Ownable.sol";


/**
* @title WhitelistedCrowdsale
* @dev Crowdsale in which only whitelisted users can contribute.
* @dev (using explicit Ownable inheritance even though Whitelist already inherits)
Copy link
Contributor

Choose a reason for hiding this comment

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

any reason for this?

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 being explicit about this when a contract uses features of a transitively-inherited one. But in this case WhitelistedCrowdsale itself doesn't use Ownable after this PR so I'd vote for removing the explicit inheritance.

isWhitelisted(_beneficiary)
internal
Copy link
Contributor

Choose a reason for hiding this comment

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

according to http://solidity.readthedocs.io/en/v0.4.24/style-guide.html:
"The visibility modifier for a function should come before any custom modifiers.".
I've requested a solium rule for this: duaraghav8/Ethlint#216

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.

It's cool that the tests needed just minor modifications for this to pass :)

As usual, I'm full of questions. Sorry about that. And I have a request on the tests, let me know what do you think.



contract WhitelistedCrowdsaleImpl is WhitelistedCrowdsale {
contract WhitelistedCrowdsaleImpl is Crowdsale, WhitelistedCrowdsale {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this needed?

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 needed; I added it to be explicit about the inheritance. But I'm not particularly attached to it ¯_(ツ)_/¯

@@ -11,84 +11,88 @@ import "./rbac/RBAC.sol";
* @dev This simplifies the implementation of "user permissions".
*/
contract Whitelist is Ownable, RBAC {
event WhitelistedAddressAdded(address addr);
event WhitelistedAddressRemoved(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.

Why to remove 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.

The RoleAdded/Removed events cover this use case :)

string public constant ROLE_WHITELISTED = "whitelist";

/**
* @dev Throws if called by any account that's not whitelisted.
* @dev kept as `onlyWhitelisted` for backwards compatibility
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is deprecated, it's nice to mention the name of the modifier that replaces it.


/**
* @dev reverts if addr does not have role
* @param addr address
* @param roleName the name of the role
* @param _operator address
Copy link
Contributor

Choose a reason for hiding this comment

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

nice!

@@ -27,7 +27,7 @@ contract('Whitelist', function (accounts) {
it('should add address to the whitelist', async function () {
await expectEvent.inTransaction(
mock.addAddressToWhitelist(whitelistedAddress1, { from: owner }),
'WhitelistedAddressAdded'
'RoleAdded'
Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh, I see, we were triggering two events.
It would be nice to check here that the role added is whitelist.

@@ -47,7 +47,7 @@ contract('Whitelist', function (accounts) {
it('should remove address from the whitelist', async function () {
await expectEvent.inTransaction(
mock.removeAddressFromWhitelist(whitelistedAddress1, { from: owner }),
'WhitelistedAddressRemoved'
'RoleRemoved'
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment about checking the role name.

@shrugs
Copy link
Contributor Author

shrugs commented Jun 8, 2018

updated!

@wilhempujar
Copy link

Nice @shrugs and @ElOpio ! This has been an issue on our end as well :)

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.

Code quality improvements! 👏

Left some comments here and there.

Also, to be clear, this PR is not fixing #979 because that issue was resolved by proper use of Truffle, right?

import "../../ownership/Ownable.sol";


/**
* @title WhitelistedCrowdsale
* @dev Crowdsale in which only whitelisted users can contribute.
* @dev (using explicit Ownable inheritance even though Whitelist already inherits)
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 being explicit about this when a contract uses features of a transitively-inherited one. But in this case WhitelistedCrowdsale itself doesn't use Ownable after this PR so I'd vote for removing the explicit inheritance.

event RoleAdded(address addr, string roleName);
event RoleRemoved(address addr, string roleName);
event RoleAdded(address indexed _operator, string _role);
event RoleRemoved(address indexed _operator, string _role);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a convention for underscores in event arguments?

I hate that these are breaking changes but string _role should probably be indexed as well. I bet you didn't make it so because of the issue with indexed strings. This got me thinking and I opened #992 to discuss some workarounds.

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 don't think we have a convention, no. Actually now that you mention it, I don't think I've seen underscored event args, so I'll remove that.

@@ -7,6 +7,7 @@ contract WhitelistMock is Whitelist {

function onlyWhitelistedCanDoThis()
onlyWhitelisted
isWhitelisted(msg.sender)
Copy link
Contributor

Choose a reason for hiding this comment

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

One of the two modifiers is redundant here right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup! Was being lazy and tested both codepaths at the same time. Honestly I'm just going to remove isWhitelisted and stick wtih onlyWhitelisted(address) because that's better anyway

/**
* @dev Throws if beneficiary is not whitelisted.
*/
modifier isWhitelisted(address _beneficiary) {
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 not sure about this modifier name. I see that it's the same modifier used in WhitelistedCrowdsale, but I'm more used to modifiers written with something like only... or when....

is... doesn't feel like it modifies anything to me. I'd love to hear some thoughts on this, and to figure out a reasonable convention for modifier names that we can document somewhere in the project.

@shrugs shrugs force-pushed the fix/whitelisted-crowdsale branch from 1cdf818 to 03c42f8 Compare June 10, 2018 22:41
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.

Big +1. Thank you @shrugs.
I like onlyIfWhitelisted. But I'm not very good at naming, I'm only good at complaining about bad names :)

@shrugs shrugs force-pushed the fix/whitelisted-crowdsale branch from 03c42f8 to c7dbf17 Compare June 15, 2018 19:17
@shrugs shrugs merged commit 92b695f into OpenZeppelin:master Jun 15, 2018
@shrugs shrugs deleted the fix/whitelisted-crowdsale branch June 15, 2018 21:11
nventuro pushed a commit to nventuro/openzeppelin-contracts that referenced this pull request Jun 18, 2018
* fix: swithc WhitelistedCrowdsale to use Whitelist.sol

* feat: refactor whitelist.sol, rbac.sol and whitelistedcrowdsale.sol

* feat: add event arg assets and update whitelist

* fix: update modifier comment and also test isWhitelisted

* fix: remove onlyWhitelisted backwards compat attempt, fix explicit inheritance

* fix: remove underscore prefix from event args

* fix: user access/Whitelist
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.

None yet

4 participants