Skip to content

Commit

Permalink
Merge branch 'master' into rename-openzeppelin-solidity
Browse files Browse the repository at this point in the history
  • Loading branch information
frangio committed Apr 26, 2018
2 parents 9c26257 + 5be9582 commit f784c8e
Show file tree
Hide file tree
Showing 149 changed files with 3,716 additions and 1,602 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE.md
Expand Up @@ -12,7 +12,7 @@
Next, we need to know what your environment looks like.

- Which version of OpenZeppelin are you using?
- What network are you deploying to? testrpc? Ganache? Ropsten?
- What network are you deploying to? Ganache? Ropsten?
- How are you deploying your OpenZeppelin-backed contracts? truffle? Remix? Let us know!

## 📝 Details
Expand Down
4 changes: 2 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Expand Up @@ -11,7 +11,7 @@ Fixes #

<!-- 3. Before submitting, please review the following checklist: -->

- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](/docs/CONTRIBUTING.md)
- [ ] 📘 I've reviewed the [OpenZeppelin Contributor Guidelines](../blob/master/CONTRIBUTING.md)
- [ ] ✅ 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`).
- [ ] 🎨 I've run the JS/Solidity linters and fixed any issues (`npm run lint:all:fix`).
1 change: 1 addition & 0 deletions .soliumrc.json
Expand Up @@ -3,6 +3,7 @@
"plugins": ["security"],
"rules": {
"quotes": ["error", "double"],
"no-empty-blocks": "off",
"indentation": ["error", 2],
"arg-overflow": ["warning", 3],
"security/enforce-explicit-visibility": ["error"],
Expand Down
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -10,10 +10,12 @@ cache:
env:
-
- SOLIDITY_COVERAGE=true
- SOLC_NIGHTLY=true
matrix:
fast_finish: true
allow_failures:
- env: SOLIDITY_COVERAGE=true
- env: SOLC_NIGHTLY=true
before_script:
- truffle version
script:
Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Expand Up @@ -12,7 +12,6 @@ Smart contracts manage value and are highly vulnerable to errors and attacks. We
As a contributor, you are expected to fork this repository, work on your own fork and then submit pull requests. The pull requests will be reviewed and eventually merged into the main repo. See ["Fork-a-Repo"](https://help.github.com/articles/fork-a-repo/) for how this works.

*IMPORTANT*
* Please use `rebase` instead of `merge` when updating your fork.
* Please see ["Git flow wiki entry"](https://github.com/OpenZeppelin/openzeppelin-solidity/wiki/Git-flow) for understanding how to use branches in this repository.

## A typical workflow
Expand Down
20 changes: 1 addition & 19 deletions README.md
Expand Up @@ -31,7 +31,7 @@ npm install -E openzeppelin-solidity

After that, you'll get all the library's contracts in the `node_modules/openzeppelin-solidity/contracts` folder. You can use the contracts in the library like so:

```js
```solidity
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';
contract MyContract is Ownable {
Expand Down Expand Up @@ -60,23 +60,5 @@ Interested in contributing to OpenZeppelin?
- Contribution guidelines: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/CONTRIBUTING.md
- Wiki: https://github.com/OpenZeppelin/openzeppelin-solidity/wiki

## Collaborating organizations and audits by OpenZeppelin
- [Golem](https://golem.network/)
- [Mediachain](http://www.mediachain.io/)
- [Truffle](http://truffleframework.com/)
- [Firstblood](https://firstblood.io/)
- [Rootstock](https://www.rsk.co/)
- [Consensys](https://consensys.net/)
- [DigixGlobal](https://www.dgx.io/)
- [Coinfund](https://coinfund.io/)
- [DemocracyEarth](https://democracy.earth/)
- [Signatura](https://signatura.co/)
- [Ether.camp](http://www.ether.camp/)
- [Aragon](https://aragon.one/)
- [Wings](https://wings.ai/)

among others...


## License
Code released under the [MIT License](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/LICENSE).
2 changes: 2 additions & 0 deletions contracts/.npmignore
@@ -0,0 +1,2 @@
mocks
examples
17 changes: 12 additions & 5 deletions contracts/AddressUtils.sol
@@ -1,20 +1,27 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


/**
* Utility library of inline functions on addresses
*/
library AddressUtils {

/**
* Returns whether there is code in the target address
* 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.
* @param addr address address to check
* @return whether there is code in the target address
* @param addr address to check
* @return whether the target address is a contract
*/
function isContract(address addr) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(addr) }
// XXX Currently there is no better way to check if there is a contract in an address
// than to check the size of the code at that address.
// See https://ethereum.stackexchange.com/a/14016/36603
// for more details about how this works.
// TODO Check this again before the Serenity release, because all addresses will be
// contracts then.
assembly { size := extcodesize(addr) } // solium-disable-line security/no-inline-assembly
return size > 0;
}

Expand Down
6 changes: 3 additions & 3 deletions contracts/Bounty.sol
@@ -1,4 +1,4 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


import "./payment/PullPayment.sol";
Expand Down Expand Up @@ -30,7 +30,7 @@ contract Bounty is PullPayment, Destructible {
function createTarget() public returns(Target) {
Target target = Target(deployContract());
researchers[target] = msg.sender;
TargetCreated(target);
emit TargetCreated(target);
return target;
}

Expand All @@ -43,7 +43,7 @@ contract Bounty is PullPayment, Destructible {
require(researcher != 0);
// Check Target contract invariants
require(!target.checkInvariant());
asyncSend(researcher, this.balance);
asyncSend(researcher, address(this).balance);
claimed = true;
}

Expand Down
5 changes: 3 additions & 2 deletions contracts/DayLimit.sol
@@ -1,4 +1,4 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


/**
Expand Down Expand Up @@ -61,7 +61,8 @@ contract DayLimit {
* @return uint256 of today's index.
*/
function today() private view returns (uint256) {
return now / 1 days;
// solium-disable-next-line security/no-block-members
return block.timestamp / 1 days;
}

/**
Expand Down
35 changes: 32 additions & 3 deletions contracts/ECRecovery.sol
@@ -1,10 +1,14 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


/**
* @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 All @@ -14,17 +18,24 @@ library ECRecovery {
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
* @param sig bytes signature, the signature is generated using web3.eth.sign()
*/
function recover(bytes32 hash, bytes sig) internal pure returns (address) {
function recover(bytes32 hash, bytes sig)
internal
pure
returns (address)
{
bytes32 r;
bytes32 s;
uint8 v;

//Check the signature length
// Check the signature length
if (sig.length != 65) {
return (address(0));
}

// Divide the signature in r, s and v variables
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
Expand All @@ -40,8 +51,26 @@ library ECRecovery {
if (v != 27 && v != 28) {
return (address(0));
} else {
// solium-disable-next-line arg-overflow
return ecrecover(hash, v, r, s);
}
}

/**
* toEthSignedMessageHash
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
* @dev and hash the result
*/
function toEthSignedMessageHash(bytes32 hash)
internal
pure
returns (bytes32)
{
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(
"\x19Ethereum Signed Message:\n32",
hash
);
}
}
4 changes: 2 additions & 2 deletions contracts/LimitBalance.sol
@@ -1,4 +1,4 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


/**
Expand All @@ -23,7 +23,7 @@ contract LimitBalance {
* @dev Checks if limit was reached. Case true, it throws.
*/
modifier limitedPayable() {
require(this.balance <= limit);
require(address(this).balance <= limit);
_;

}
Expand Down
17 changes: 4 additions & 13 deletions contracts/MerkleProof.sol
@@ -1,4 +1,4 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


/*
Expand All @@ -14,20 +14,11 @@ library MerkleProof {
* @param _root Merkle root
* @param _leaf Leaf of Merkle tree
*/
function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
// Check if proof length is a multiple of 32
if (_proof.length % 32 != 0) {
return false;
}

bytes32 proofElement;
function verifyProof(bytes32[] _proof, bytes32 _root, bytes32 _leaf) internal pure returns (bool) {
bytes32 computedHash = _leaf;

for (uint256 i = 32; i <= _proof.length; i += 32) {
assembly {
// Load the current element of the proof
proofElement := mload(add(_proof, i))
}
for (uint256 i = 0; i < _proof.length; i++) {
bytes32 proofElement = _proof[i];

if (computedHash < proofElement) {
// Hash(current computed hash + current element of the proof)
Expand Down
10 changes: 5 additions & 5 deletions contracts/ReentrancyGuard.sol
@@ -1,4 +1,4 @@
pragma solidity ^0.4.18;
pragma solidity ^0.4.21;


/**
Expand All @@ -12,7 +12,7 @@ contract ReentrancyGuard {
/**
* @dev We use a single lock for the whole contract.
*/
bool private reentrancy_lock = false;
bool private reentrancyLock = false;

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
Expand All @@ -23,10 +23,10 @@ contract ReentrancyGuard {
* wrapper marked as `nonReentrant`.
*/
modifier nonReentrant() {
require(!reentrancy_lock);
reentrancy_lock = true;
require(!reentrancyLock);
reentrancyLock = true;
_;
reentrancy_lock = false;
reentrancyLock = false;
}

}
90 changes: 90 additions & 0 deletions contracts/access/SignatureBouncer.sol
@@ -0,0 +1,90 @@
pragma solidity ^0.4.18;

import "../ownership/Ownable.sol";
import "../ownership/rbac/RBAC.sol";
import "../ECRecovery.sol";

/**
* @title SignatureBouncer
* @author PhABC and Shrugs
* @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(`: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 See the tests Bouncer.test.js for specific usage examples.
*/
contract SignatureBouncer is Ownable, RBAC {
using ECRecovery for bytes32;

string public constant ROLE_BOUNCER = "bouncer";

/**
* @dev requires that a valid signature of a bouncer was provided
*/
modifier onlyValidSignature(bytes _sig)
{
require(isValidSignature(msg.sender, _sig));
_;
}

/**
* @dev allows the owner to add additional bouncer addresses
*/
function addBouncer(address _bouncer)
onlyOwner
public
{
require(_bouncer != address(0));
addRole(_bouncer, ROLE_BOUNCER);
}

/**
* @dev allows the owner to remove bouncer addresses
*/
function removeBouncer(address _bouncer)
onlyOwner
public
{
require(_bouncer != address(0));
removeRole(_bouncer, ROLE_BOUNCER);
}

/**
* @dev is the signature of `this + sender` from a bouncer?
* @return bool
*/
function isValidSignature(address _address, bytes _sig)
internal
view
returns (bool)
{
return isValidDataHash(
keccak256(address(this), _address),
_sig
);
}

/**
* @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
* @return bool
*/
function isValidDataHash(bytes32 hash, bytes _sig)
internal
view
returns (bool)
{
address signer = hash
.toEthSignedMessageHash()
.recover(_sig);
return hasRole(signer, ROLE_BOUNCER);
}
}

0 comments on commit f784c8e

Please sign in to comment.