-
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
Add Whitelist contract #746
Conversation
contracts/ownership/Whitelist.sol
Outdated
* @dev Throws if called by any account that's not whitelisted and not an owner. | ||
*/ | ||
modifier onlyWhitelisted() { | ||
require(whitelist[msg.sender] || owner == 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.
The owner can add himself to whitelist if he wants to buy tokens, what about checking only 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.
@AugustoL I think this will be more flexible because the owner can add and remove himself if he wants. On the other hand, I can't think of a situation when an owner doesn't want himself to be whitelisted for some operation. I guess it will be more for preventing errors than for authorization in this case, because the owner can whitelist himself at any time?
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 never saw the owner of the contract receiving tokens. I guess we can leave it but in my experience the owner of the ICO not always receives tokens or ETH, they are forwarded to another wallets, multisig, vestedPayments, etc. That is why O would not assume the owner will want any tokens, and in that case he can whitelist himself.
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 wouldn't think of this in terms of what the owner wants, I would adjust the behavior to the semantics instead. This modifier should only check whether an address is in the whitelist or not as its name promises.
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.
Done
contracts/ownership/Whitelist.sol
Outdated
* @dev add an address to the whitelist | ||
* @param addr address | ||
*/ | ||
function addToWhitelist(address addr) onlyOwner public returns(bool) { |
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.
What about using an array of addresses instead of just one? if I want to add 100 whitelisted addresses I have to make 100 txs,
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.
Good idea. I'll do it. Will do the same for removeFromWhitelist()
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.
Would you mind setting a different function for it? Creating an array of 1 element seems clunky for this particular action.
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.
sure.
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.
Done
contracts/ownership/Whitelist.sol
Outdated
* @param addr address | ||
*/ | ||
function removeFromWhitelist(address addr) onlyOwner public returns(bool) { | ||
if (!whitelist[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.
can you use require
instead of returning bools?
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.
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.
Intaht case we can still return bool and only leave the return true at the end of the function,
function addToWhitelist(address[] addrs) onlyOwner public returns(bool) {
for(uint256 i = 0; i < addrs.length; i ++) {
require(!whitelist[addrs[i]]);
whitelist[addrs[i]] = true;
WhitelistedAddressAdded(addrs[i]);
}
return true;
}
We should also check that the receiver address is not 0x.
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.
@AugustoL I see no point in that revert. Sending a list of 100 addresses where only 1 is already whitelisted would result in a tremendous gas waste with no upside.
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.
@martriay ture, and we dont even need to check that the address is not 0x, the address 0x it wont be able to make any call to the contract, so is the same to have it or not. So no requires needed in the add/remove whitelist functions?
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 would call the return value success
to make this easier to think. I would say that if 99 addresses were whitelisted and only 1 skipped, it should return true
.
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.
@martriay any objections against returning successCount
?
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 would differ in style with the one-element whitelisting (that would return bool
) and make the caller compare the result with the original amount sent, having little knowledge about which addresses have failed (events cannot be seen within the blockchain). As I don't see what can the caller do with that number, I prefer the success
bool for being simple enough, and the if
clausule will be nicer 😊.
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.
Guys looks like truffle doesn't support overloaded functions (we need it for addToWhitelist
that accepts a single address and an array). Right now I get intermittent errors "TypeError: value.forEach is not a function" and "Error: new BigNumber() not a base 16 number: f17f52151ebef6c7334fad080c5704d77216b732,0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef"
There is a PR here https://github.com/trufflesuite/truffle-contract/pull/75 but it's still open. There is a workaround here but it's bulky https://beresnev.pro/test-overloaded-solidity-functions-via-truffle/.
Should I just leave a TODO for now in tests and wait until it's fixed in truffle? Another option is to disambiguate addToWhitelist
to addAddressToWhitelist
and addAddressesToWhitelist
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.
Done. Decided to disambiguate methods.
contracts/mocks/WhitelistMock.sol
Outdated
@@ -0,0 +1,14 @@ | |||
pragma solidity ^0.4.8; |
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.
Was using 0.4.8 intentional here?
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.
@redsquirrel Not really.
Should I use pragma solidity ^0.4.18;
? I found most contracts here use this pragma, however some contracts are different. Do you have any guidelines for the compiler version?
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.
Yes please, use .18 :)
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.
Done
I feel like this is a specific case of RBAC—would it be reasonable to inherit from RBAC and store a |
@shrugs Indeed, this is a specific case, but a very common one. I think it's a good idea to have them separated since otherwise people would have to extend RBAC with unnecessary additional logic that's only increasing the attack surface. |
Seems reasonable to me 👍 |
@martriay any plans on merging this PR? |
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.
nitpick: sorry about that. otherwise LGTM
contracts/ownership/Whitelist.sol
Outdated
/** | ||
* @title Whitelist | ||
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control | ||
* functions, this simplifies the implementation of "user permissions". |
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.
let's add an @dev
prefix here for multiple-line dev comments
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.
Done.
* Add Whitelist contract
* Add Whitelist contract
Implements #743
🚀 Description
Added Whitelist contract and tests.