Skip to content

Commit

Permalink
Merge branch 'master' into fix/OpenZeppelin#977
Browse files Browse the repository at this point in the history
  • Loading branch information
YZhenY authored Jun 22, 2018
2 parents a417377 + f18c3bc commit 2b9b716
Show file tree
Hide file tree
Showing 35 changed files with 269 additions and 261 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ build/

# lol macs
.DS_Store/

# truffle
.node-xmlhttprequest-*
2 changes: 1 addition & 1 deletion contracts/AddressUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ library AddressUtils {
/**
* Returns whether the target address is a contract
* @dev This function will return false if invoked during the constructor of a contract,
* as the code is not actually created until after the constructor finishes.
* as the code is not actually created until after the constructor finishes.
* @param addr address to check
* @return whether the target address is a contract
*/
Expand Down
5 changes: 1 addition & 4 deletions contracts/ECRecovery.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ pragma solidity ^0.4.24;

/**
* @title Eliptic curve signature operations
*
* @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
*
* TODO Remove this library once solidity supports passing a signature to ecrecover.
* See https://github.com/ethereum/solidity/issues/864
*
*/

library ECRecovery {
Expand Down Expand Up @@ -59,7 +56,7 @@ library ECRecovery {
/**
* toEthSignedMessageHash
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
* @dev and hash the result
* and hash the result
*/
function toEthSignedMessageHash(bytes32 hash)
internal
Expand Down
4 changes: 2 additions & 2 deletions contracts/LimitBalance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pragma solidity ^0.4.24;
/**
* @title LimitBalance
* @dev Simple contract to limit the balance of child contract.
* @dev Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
* @dev See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
* Note this doesn't prevent other contracts to send funds by using selfdestruct(address);
* See: https://github.com/ConsenSys/smart-contract-best-practices#remember-that-ether-can-be-forcibly-sent-to-an-account
*/
contract LimitBalance {

Expand Down
4 changes: 2 additions & 2 deletions contracts/MerkleProof.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ pragma solidity ^0.4.24;

/*
* @title MerkleProof
* @dev Merkle proof verification
* @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
* @dev Merkle proof verification based on
* https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
*/
library MerkleProof {
/*
Expand Down
41 changes: 19 additions & 22 deletions contracts/access/SignatureBouncer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,25 @@ import "../ECRecovery.sol";
* @title SignatureBouncer
* @author PhABC, Shrugs and aflesher
* @dev Bouncer allows users to submit a signature as a permission to do an action.
* @dev If the signature is from one of the authorized bouncer addresses, the signature
* @dev is valid. The owner of the contract adds/removes bouncers.
* @dev Bouncer addresses can be individual servers signing grants or different
* @dev users within a decentralized club that have permission to invite other members.
* @dev
* @dev This technique is useful for whitelists and airdrops; instead of putting all
* @dev valid addresses on-chain, simply sign a grant of the form
* @dev keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid bouncer address.
* @dev Then restrict access to your crowdsale/whitelist/airdrop using the
* @dev `onlyValidSignature` modifier (or implement your own using isValidSignature).
* @dev
* @dev In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
* @dev `onlyValidSignatureAndData` can be used to restrict access to only a given method
* @dev or a given method with given parameters respectively.
* @dev
* @dev See the tests Bouncer.test.js for specific usage examples.
* If the signature is from one of the authorized bouncer addresses, the signature
* is valid. The owner of the contract adds/removes bouncers.
* Bouncer addresses can be individual servers signing grants or different
* users within a decentralized club that have permission to invite other members.
* This technique is useful for whitelists and airdrops; instead of putting all
* valid addresses on-chain, simply sign a grant of the form
* keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a valid bouncer address.
* Then restrict access to your crowdsale/whitelist/airdrop using the
* `onlyValidSignature` modifier (or implement your own using isValidSignature).
* In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
* `onlyValidSignatureAndData` can be used to restrict access to only a given method
* or a given method with given parameters respectively.
* See the tests Bouncer.test.js for specific usage examples.
* @notice A method that uses the `onlyValidSignatureAndData` modifier must make the _sig
* @notice parameter the "last" parameter. You cannot sign a message that has its own
* @notice signature in it so the last 128 bytes of msg.data (which represents the
* @notice length of the _sig data and the _sig data itself) is ignored when validating.
* @notice Also non fixed sized parameters make constructing the data in the signature
* @notice much more complex. See https://ethereum.stackexchange.com/a/50616 for more details.
* parameter the "last" parameter. You cannot sign a message that has its own
* signature in it so the last 128 bytes of msg.data (which represents the
* length of the _sig data and the _sig data itself) is ignored when validating.
* Also non fixed sized parameters make constructing the data in the signature
* much more complex. See https://ethereum.stackexchange.com/a/50616 for more details.
*/
contract SignatureBouncer is Ownable, RBAC {
using ECRecovery for bytes32;
Expand Down Expand Up @@ -146,7 +143,7 @@ contract SignatureBouncer is Ownable, RBAC {

/**
* @dev internal function to convert a hash to an eth signed message
* @dev and then recover the signature and check it against the bouncer role
* and then recover the signature and check it against the bouncer role
* @return bool
*/
function isValidDataHash(bytes32 hash, bytes _sig)
Expand Down
46 changes: 21 additions & 25 deletions contracts/access/Whitelist.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,87 +8,83 @@ import "../ownership/rbac/RBAC.sol";
/**
* @title Whitelist
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
* @dev This simplifies the implementation of "user permissions".
* 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]);
}
}

Expand Down
6 changes: 4 additions & 2 deletions contracts/crowdsale/Crowdsale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pragma solidity ^0.4.24;

import "../token/ERC20/ERC20.sol";
import "../math/SafeMath.sol";
import "../token/ERC20/SafeERC20.sol";


/**
Expand All @@ -18,6 +19,7 @@ import "../math/SafeMath.sol";
*/
contract Crowdsale {
using SafeMath for uint256;
using SafeERC20 for ERC20;

// The token being sold
ERC20 public token;
Expand Down Expand Up @@ -147,7 +149,7 @@ contract Crowdsale {
)
internal
{
token.transfer(_beneficiary, _tokenAmount);
token.safeTransfer(_beneficiary, _tokenAmount);
}

/**
Expand Down Expand Up @@ -195,4 +197,4 @@ contract Crowdsale {
function _forwardFunds() internal {
wallet.transfer(msg.value);
}
}
}
43 changes: 3 additions & 40 deletions contracts/crowdsale/validation/WhitelistedCrowdsale.sol
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -55,8 +18,8 @@ contract WhitelistedCrowdsale is Crowdsale, Ownable {
address _beneficiary,
uint256 _weiAmount
)
onlyIfWhitelisted(_beneficiary)
internal
isWhitelisted(_beneficiary)
{
super._preValidatePurchase(_beneficiary, _weiAmount);
}
Expand Down
15 changes: 7 additions & 8 deletions contracts/examples/RBACWithAdmin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import "../ownership/rbac/RBAC.sol";
* @title RBACWithAdmin
* @author Matt Condon (@Shrugs)
* @dev It's recommended that you define constants in the contract,
* @dev like ROLE_ADMIN below, to avoid typos.
* @dev
* @dev NOTE: RBACWithAdmin is probably too expansive and powerful for your
* @dev application; an admin is actually able to change any address to any role
* @dev which is a very large API surface. It's recommended that you follow a strategy
* @dev of strictly defining the abilities of your roles
* @dev and the API-surface of your contract.
* @dev This is just an example for example's sake.
* like ROLE_ADMIN below, to avoid typos.
* @notice RBACWithAdmin is probably too expansive and powerful for your
* application; an admin is actually able to change any address to any role
* which is a very large API surface. It's recommended that you follow a strategy
* of strictly defining the abilities of your roles
* and the API-surface of your contract.
* This is just an example for example's sake.
*/
contract RBACWithAdmin is RBAC {
/**
Expand Down
2 changes: 1 addition & 1 deletion contracts/introspection/ERC165.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface ERC165 {
* @notice Query if a contract implements an interface
* @param _interfaceId The interface identifier, as specified in ERC-165
* @dev Interface identification is specified in ERC-165. This function
* @dev uses less than 30,000 gas.
* uses less than 30,000 gas.
*/
function supportsInterface(bytes4 _interfaceId)
external
Expand Down
2 changes: 1 addition & 1 deletion contracts/introspection/SupportsInterfaceWithLookup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract SupportsInterfaceWithLookup is ERC165 {

/**
* @dev A contract implementing SupportsInterfaceWithLookup
* @dev implement ERC165 itself
* implement ERC165 itself
*/
constructor()
public
Expand Down
13 changes: 13 additions & 0 deletions contracts/mocks/ERC20WithMetadataMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pragma solidity ^0.4.21;

import "../token/ERC20/StandardToken.sol";
import "../proposals/ERC1046/TokenMetadata.sol";


contract ERC20WithMetadataMock is StandardToken, ERC20WithMetadata {
function ERC20WithMetadataMock(string _tokenURI)
ERC20WithMetadata(_tokenURI)
public
{
}
}
3 changes: 1 addition & 2 deletions contracts/mocks/ReentrancyMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ contract ReentrancyMock is ReentrancyGuard {
}

function countThisRecursive(uint256 n) public nonReentrant {
bytes4 func = bytes4(keccak256("countThisRecursive(uint256)"));
if (n > 0) {
count();
// solium-disable-next-line security/no-low-level-calls
bool result = address(this).call(func, n - 1);
bool result = address(this).call(abi.encodeWithSignature("countThisRecursive(uint256)", n - 1));
require(result == true);
}
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/WhitelistMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../access/Whitelist.sol";
contract WhitelistMock is Whitelist {

function onlyWhitelistedCanDoThis()
onlyWhitelisted
onlyIfWhitelisted(msg.sender)
view
external
{
Expand Down
Loading

0 comments on commit 2b9b716

Please sign in to comment.