Fix/whitelisted crowdsale (#981)

* 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
This commit is contained in:
Matt Condon
2018-06-15 14:11:50 -07:00
committed by GitHub
parent ee78f67985
commit 92b695f2fb
8 changed files with 98 additions and 131 deletions

View File

@ -11,84 +11,80 @@ import "../ownership/rbac/RBAC.sol";
* This simplifies the implementation of "user permissions".
*/
contract Whitelist is Ownable, RBAC {
event WhitelistedAddressAdded(address addr);
event WhitelistedAddressRemoved(address addr);
string public constant ROLE_WHITELISTED = "whitelist";
/**
* @dev Throws if called by any account that's not whitelisted.
* @dev Throws if operator is not whitelisted.
* @param _operator address
*/
modifier onlyWhitelisted() {
checkRole(msg.sender, ROLE_WHITELISTED);
modifier onlyIfWhitelisted(address _operator) {
checkRole(_operator, ROLE_WHITELISTED);
_;
}
/**
* @dev add an address to the whitelist
* @param addr address
* @param _operator address
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
*/
function addAddressToWhitelist(address addr)
function addAddressToWhitelist(address _operator)
onlyOwner
public
{
addRole(addr, ROLE_WHITELISTED);
emit WhitelistedAddressAdded(addr);
addRole(_operator, ROLE_WHITELISTED);
}
/**
* @dev getter to determine if address is in whitelist
*/
function whitelist(address addr)
function whitelist(address _operator)
public
view
returns (bool)
{
return hasRole(addr, ROLE_WHITELISTED);
return hasRole(_operator, ROLE_WHITELISTED);
}
/**
* @dev add addresses to the whitelist
* @param addrs addresses
* @param _operators addresses
* @return true if at least one address was added to the whitelist,
* false if all addresses were already in the whitelist
*/
function addAddressesToWhitelist(address[] addrs)
function addAddressesToWhitelist(address[] _operators)
onlyOwner
public
{
for (uint256 i = 0; i < addrs.length; i++) {
addAddressToWhitelist(addrs[i]);
for (uint256 i = 0; i < _operators.length; i++) {
addAddressToWhitelist(_operators[i]);
}
}
/**
* @dev remove an address from the whitelist
* @param addr address
* @param _operator address
* @return true if the address was removed from the whitelist,
* false if the address wasn't in the whitelist in the first place
*/
function removeAddressFromWhitelist(address addr)
function removeAddressFromWhitelist(address _operator)
onlyOwner
public
{
removeRole(addr, ROLE_WHITELISTED);
emit WhitelistedAddressRemoved(addr);
removeRole(_operator, ROLE_WHITELISTED);
}
/**
* @dev remove addresses from the whitelist
* @param addrs addresses
* @param _operators addresses
* @return true if at least one address was removed from the whitelist,
* false if all addresses weren't in the whitelist in the first place
*/
function removeAddressesFromWhitelist(address[] addrs)
function removeAddressesFromWhitelist(address[] _operators)
onlyOwner
public
{
for (uint256 i = 0; i < addrs.length; i++) {
removeAddressFromWhitelist(addrs[i]);
for (uint256 i = 0; i < _operators.length; i++) {
removeAddressFromWhitelist(_operators[i]);
}
}

View File

@ -1,51 +1,14 @@
pragma solidity ^0.4.24;
import "../Crowdsale.sol";
import "../../ownership/Ownable.sol";
import "../../access/Whitelist.sol";
/**
* @title WhitelistedCrowdsale
* @dev Crowdsale in which only whitelisted users can contribute.
*/
contract WhitelistedCrowdsale is Crowdsale, Ownable {
mapping(address => bool) public whitelist;
/**
* @dev Reverts if beneficiary is not whitelisted. Can be used when extending this contract.
*/
modifier isWhitelisted(address _beneficiary) {
require(whitelist[_beneficiary]);
_;
}
/**
* @dev Adds single address to whitelist.
* @param _beneficiary Address to be added to the whitelist
*/
function addToWhitelist(address _beneficiary) external onlyOwner {
whitelist[_beneficiary] = true;
}
/**
* @dev Adds list of addresses to whitelist. Not overloaded due to limitations with truffle testing.
* @param _beneficiaries Addresses to be added to the whitelist
*/
function addManyToWhitelist(address[] _beneficiaries) external onlyOwner {
for (uint256 i = 0; i < _beneficiaries.length; i++) {
whitelist[_beneficiaries[i]] = true;
}
}
/**
* @dev Removes single address from whitelist.
* @param _beneficiary Address to be removed to the whitelist
*/
function removeFromWhitelist(address _beneficiary) external onlyOwner {
whitelist[_beneficiary] = false;
}
contract WhitelistedCrowdsale is Whitelist, Crowdsale {
/**
* @dev Extend parent behavior requiring beneficiary to be in whitelist.
* @param _beneficiary Token beneficiary
@ -55,8 +18,8 @@ contract WhitelistedCrowdsale is Crowdsale, Ownable {
address _beneficiary,
uint256 _weiAmount
)
onlyIfWhitelisted(_beneficiary)
internal
isWhitelisted(_beneficiary)
{
super._preValidatePurchase(_beneficiary, _weiAmount);
}

View File

@ -5,7 +5,7 @@ import "../access/Whitelist.sol";
contract WhitelistMock is Whitelist {
function onlyWhitelistedCanDoThis()
onlyWhitelisted
onlyIfWhitelisted(msg.sender)
view
external
{

View File

@ -2,18 +2,18 @@ pragma solidity ^0.4.24;
import "../token/ERC20/ERC20.sol";
import "../crowdsale/validation/WhitelistedCrowdsale.sol";
import "../crowdsale/Crowdsale.sol";
contract WhitelistedCrowdsaleImpl is WhitelistedCrowdsale {
contract WhitelistedCrowdsaleImpl is Crowdsale, WhitelistedCrowdsale {
constructor (
uint256 _rate,
address _wallet,
ERC20 _token
)
public
Crowdsale(_rate, _wallet, _token)
public
{
}
}

View File

@ -19,83 +19,83 @@ contract RBAC {
mapping (string => Roles.Role) private roles;
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);
/**
* @dev reverts if addr does not have role
* @param addr address
* @param roleName the name of the role
* @param _operator address
* @param _role the name of the role
* // reverts
*/
function checkRole(address addr, string roleName)
function checkRole(address _operator, string _role)
view
public
{
roles[roleName].check(addr);
roles[_role].check(_operator);
}
/**
* @dev determine if addr has role
* @param addr address
* @param roleName the name of the role
* @param _operator address
* @param _role the name of the role
* @return bool
*/
function hasRole(address addr, string roleName)
function hasRole(address _operator, string _role)
view
public
returns (bool)
{
return roles[roleName].has(addr);
return roles[_role].has(_operator);
}
/**
* @dev add a role to an address
* @param addr address
* @param roleName the name of the role
* @param _operator address
* @param _role the name of the role
*/
function addRole(address addr, string roleName)
function addRole(address _operator, string _role)
internal
{
roles[roleName].add(addr);
emit RoleAdded(addr, roleName);
roles[_role].add(_operator);
emit RoleAdded(_operator, _role);
}
/**
* @dev remove a role from an address
* @param addr address
* @param roleName the name of the role
* @param _operator address
* @param _role the name of the role
*/
function removeRole(address addr, string roleName)
function removeRole(address _operator, string _role)
internal
{
roles[roleName].remove(addr);
emit RoleRemoved(addr, roleName);
roles[_role].remove(_operator);
emit RoleRemoved(_operator, _role);
}
/**
* @dev modifier to scope access to a single role (uses msg.sender as addr)
* @param roleName the name of the role
* @param _role the name of the role
* // reverts
*/
modifier onlyRole(string roleName)
modifier onlyRole(string _role)
{
checkRole(msg.sender, roleName);
checkRole(msg.sender, _role);
_;
}
/**
* @dev modifier to scope access to a set of roles (uses msg.sender as addr)
* @param roleNames the names of the roles to scope access to
* @param _roles the names of the roles to scope access to
* // reverts
*
* @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this
* see: https://github.com/ethereum/solidity/issues/2467
*/
// modifier onlyRoles(string[] roleNames) {
// modifier onlyRoles(string[] _roles) {
// bool hasAnyRole = false;
// for (uint8 i = 0; i < roleNames.length; i++) {
// if (hasRole(msg.sender, roleNames[i])) {
// for (uint8 i = 0; i < _roles.length; i++) {
// if (hasRole(msg.sender, _roles[i])) {
// hasAnyRole = true;
// break;
// }