-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Conversation
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) |
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.
any reason for this?
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 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 |
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.
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
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.
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 { |
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.
Is this needed?
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 needed; I added it to be explicit about the inheritance. But I'm not particularly attached to it ¯_(ツ)_/¯
contracts/ownership/Whitelist.sol
Outdated
@@ -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); |
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.
Why to remove these?
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.
The RoleAdded/Removed events cover this use case :)
contracts/ownership/Whitelist.sol
Outdated
string public constant ROLE_WHITELISTED = "whitelist"; | ||
|
||
/** | ||
* @dev Throws if called by any account that's not whitelisted. | ||
* @dev kept as `onlyWhitelisted` for backwards compatibility |
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.
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 |
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.
nice!
test/ownership/Whitelist.test.js
Outdated
@@ -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' |
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.
Ahh, I see, we were triggering two events.
It would be nice to check here that the role added is whitelist
.
test/ownership/Whitelist.test.js
Outdated
@@ -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' |
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.
same comment about checking the role name.
updated! |
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.
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) |
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 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.
contracts/ownership/rbac/RBAC.sol
Outdated
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); |
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.
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.
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 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.
contracts/mocks/WhitelistMock.sol
Outdated
@@ -7,6 +7,7 @@ contract WhitelistMock is Whitelist { | |||
|
|||
function onlyWhitelistedCanDoThis() | |||
onlyWhitelisted | |||
isWhitelisted(msg.sender) |
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.
One of the two modifiers is redundant here right?
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.
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
contracts/ownership/Whitelist.sol
Outdated
/** | ||
* @dev Throws if beneficiary is not whitelisted. | ||
*/ | ||
modifier isWhitelisted(address _beneficiary) { |
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 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.
1cdf818
to
03c42f8
Compare
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.
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 :)
03c42f8
to
c7dbf17
Compare
* 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
🚀 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.
npm run lint:all:fix
).