Browse Source

Merge with upstream/master

Rudy Godoy 8 years ago
parent
commit
6904f12032
74 changed files with 1821 additions and 366 deletions
  1. 5 0
      .solcover.js
  2. 2 3
      .travis.yml
  3. 8 14
      contracts/Bounty.sol
  4. 1 3
      contracts/DayLimit.sol
  5. 47 0
      contracts/ECRecovery.sol
  6. 2 4
      contracts/LimitBalance.sol
  7. 17 19
      contracts/MultisigWallet.sol
  8. 5 8
      contracts/ReentrancyGuard.sol
  9. 0 48
      contracts/SafeMath.sol
  10. 34 0
      contracts/crowdsale/CappedCrowdsale.sol
  11. 107 0
      contracts/crowdsale/Crowdsale.sol
  12. 39 0
      contracts/crowdsale/FinalizableCrowdsale.sol
  13. 56 0
      contracts/crowdsale/RefundVault.sol
  14. 60 0
      contracts/crowdsale/RefundableCrowdsale.sol
  15. 2 2
      contracts/lifecycle/Pausable.sol
  16. 24 0
      contracts/math/Math.sol
  17. 32 0
      contracts/math/SafeMath.sol
  18. 5 7
      contracts/ownership/Claimable.sol
  19. 7 9
      contracts/ownership/DelayedClaimable.sol
  20. 6 10
      contracts/ownership/HasNoEther.sol
  21. 3 3
      contracts/ownership/HasNoTokens.sol
  22. 6 8
      contracts/ownership/Ownable.sol
  23. 9 15
      contracts/ownership/Shareable.sol
  24. 4 11
      contracts/payment/PullPayment.sol
  25. 3 2
      contracts/token/BasicToken.sol
  26. 0 60
      contracts/token/CrowdsaleToken.sol
  27. 2 2
      contracts/token/ERC20.sol
  28. 2 2
      contracts/token/ERC20Basic.sol
  29. 10 10
      contracts/token/LimitedTransferToken.sol
  30. 1 1
      contracts/token/MintableToken.sol
  31. 5 9
      contracts/token/PausableToken.sol
  32. 8 6
      contracts/token/StandardToken.sol
  33. 49 0
      contracts/token/TokenTimelock.sol
  34. 9 15
      contracts/token/VestedToken.sol
  35. 0 14
      docs/source/crowdsaletoken.rst
  36. 9 0
      docs/source/ecrecovery.rst
  37. 1 1
      docs/source/getting-started.rst
  38. 24 0
      docs/source/math.rst
  39. 2 2
      docs/source/ownable.rst
  40. 4 4
      docs/source/safemath.rst
  41. 1 1
      ethpm.json
  42. 6 2
      package.json
  43. 23 1
      scripts/coverage.sh
  44. 14 2
      scripts/test.sh
  45. 90 0
      test/CappedCrowdsale.js
  46. 143 0
      test/Crowdsale.js
  47. 26 1
      test/DayLimit.js
  48. 55 0
      test/ECRecovery.js
  49. 61 0
      test/FinalizableCrowdsale.js
  50. 1 1
      test/MultisigWallet.js
  51. 61 0
      test/RefundVault.js
  52. 76 0
      test/RefundableCrowdsale.js
  53. 58 0
      test/TokenTimelock.js
  54. 1 1
      test/helpers/BasicTokenMock.sol
  55. 21 0
      test/helpers/CappedCrowdsaleImpl.sol
  56. 4 4
      test/helpers/DayLimitMock.sol
  57. 3 3
      test/helpers/ERC23TokenMock.sol
  58. 1 0
      test/helpers/EVMThrow.js
  59. 20 0
      test/helpers/FinalizableCrowdsaleImpl.sol
  60. 2 2
      test/helpers/MultisigWalletMock.sol
  61. 1 1
      test/helpers/PausableMock.sol
  62. 1 1
      test/helpers/PullPaymentMock.sol
  63. 1 1
      test/helpers/ReentrancyMock.sol
  64. 21 0
      test/helpers/RefundableCrowdsaleImpl.sol
  65. 5 5
      test/helpers/SafeMathMock.sol
  66. 2 2
      test/helpers/ShareableMock.sol
  67. 1 1
      test/helpers/StandardTokenMock.sol
  68. 1 1
      test/helpers/VestedTokenMock.sol
  69. 22 0
      test/helpers/advanceToBlock.js
  70. 3 0
      test/helpers/ether.js
  71. 8 0
      test/helpers/hashMessage.js
  72. 23 0
      test/helpers/increaseTime.js
  73. 6 0
      test/helpers/latestTime.js
  74. 449 44
      yarn.lock

+ 5 - 0
.solcover.js

@@ -0,0 +1,5 @@
+module.exports = {
+    norpc: true,
+    testCommand: 'node --max-old-space-size=4096 ../node_modules/.bin/truffle test --network coverage',
+    skipFiles: ['lifecycle/Migrations.sol']
+}

+ 2 - 3
.travis.yml

@@ -1,5 +1,5 @@
 dist: trusty
 dist: trusty
-sudo: false
+sudo: required
 group: beta
 group: beta
 language: node_js
 language: node_js
 node_js:
 node_js:
@@ -7,7 +7,6 @@ node_js:
 cache:
 cache:
   yarn: true
   yarn: true
 script:
 script:
-  - testrpc > /dev/null &
-  - truffle test
+  - yarn test
 after_script:
 after_script:
   - yarn run coveralls
   - yarn run coveralls

+ 8 - 14
contracts/Bounty.sol

@@ -19,13 +19,11 @@ contract Bounty is PullPayment, Destructible {
    * @dev Fallback function allowing the contract to recieve funds, if they haven't already been claimed.
    * @dev Fallback function allowing the contract to recieve funds, if they haven't already been claimed.
    */
    */
   function() payable {
   function() payable {
-    if (claimed) {
-      throw;
-    }
+    require(!claimed);
   }
   }
 
 
   /**
   /**
-   * @dev Create and deploy the target contract (extension of Target contract), and sets the 
+   * @dev Create and deploy the target contract (extension of Target contract), and sets the
    * msg.sender as a researcher
    * msg.sender as a researcher
    * @return A target contract
    * @return A target contract
    */
    */
@@ -48,13 +46,9 @@ contract Bounty is PullPayment, Destructible {
    */
    */
   function claim(Target target) {
   function claim(Target target) {
     address researcher = researchers[target];
     address researcher = researchers[target];
-    if (researcher == 0) {
-      throw;
-    }
+    require(researcher != 0);
     // Check Target contract invariants
     // Check Target contract invariants
-    if (target.checkInvariant()) {
-      throw;
-    }
+    require(!target.checkInvariant());
     asyncSend(researcher, this.balance);
     asyncSend(researcher, this.balance);
     claimed = true;
     claimed = true;
   }
   }
@@ -69,10 +63,10 @@ contract Bounty is PullPayment, Destructible {
 contract Target {
 contract Target {
 
 
    /**
    /**
-    * @dev Checks all values a contract assumes to be true all the time. If this function returns 
-    * false, the contract is broken in some way and is in an inconsistent state. 
-    * In order to win the bounty, security researchers will try to cause this broken state. 
-    * @return True if all invariant values are correct, false otherwise. 
+    * @dev Checks all values a contract assumes to be true all the time. If this function returns
+    * false, the contract is broken in some way and is in an inconsistent state.
+    * In order to win the bounty, security researchers will try to cause this broken state.
+    * @return True if all invariant values are correct, false otherwise.
     */
     */
   function checkInvariant() returns(bool);
   function checkInvariant() returns(bool);
 }
 }

+ 1 - 3
contracts/DayLimit.sol

@@ -67,9 +67,7 @@ contract DayLimit {
    * @dev Simple modifier for daily limit.
    * @dev Simple modifier for daily limit.
    */
    */
   modifier limitedDaily(uint256 _value) {
   modifier limitedDaily(uint256 _value) {
-    if (!underLimit(_value)) {
-      throw;
-    }
+    require(underLimit(_value));
     _;
     _;
   }
   }
 }
 }

+ 47 - 0
contracts/ECRecovery.sol

@@ -0,0 +1,47 @@
+pragma solidity ^0.4.11;
+
+
+/**
+ * @title Eliptic curve signature operations
+ *
+ * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
+ */
+
+library ECRecovery {
+
+  /**
+   * @dev Recover signer address from a message by using his signature
+   * @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) constant returns (address) {
+    bytes32 r;
+    bytes32 s;
+    uint8 v;
+
+    //Check the signature length
+    if (sig.length != 65) {
+      return (address(0));
+    }
+
+    // Divide the signature in r, s and v variables
+    assembly {
+      r := mload(add(sig, 32))
+      s := mload(add(sig, 64))
+      v := byte(0, mload(add(sig, 96)))
+    }
+
+    // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
+    if (v < 27) {
+      v += 27;
+    }
+
+    // If the version is correct return the signer address
+    if (v != 27 && v != 28) {
+      return (address(0));
+    } else {
+      return ecrecover(hash, v, r, s);
+    }
+  }
+
+}

+ 2 - 4
contracts/LimitBalance.sol

@@ -12,7 +12,7 @@ contract LimitBalance {
   uint256 public limit;
   uint256 public limit;
 
 
   /**
   /**
-   * @dev Constructor that sets the passed value as a limit. 
+   * @dev Constructor that sets the passed value as a limit.
    * @param _limit uint256 to represent the limit.
    * @param _limit uint256 to represent the limit.
    */
    */
   function LimitBalance(uint256 _limit) {
   function LimitBalance(uint256 _limit) {
@@ -23,9 +23,7 @@ contract LimitBalance {
    * @dev Checks if limit was reached. Case true, it throws.
    * @dev Checks if limit was reached. Case true, it throws.
    */
    */
   modifier limitedPayable() {
   modifier limitedPayable() {
-    if (this.balance > limit) {
-      throw;
-    }
+    require(this.balance <= limit);
     _;
     _;
 
 
   }
   }

+ 17 - 19
contracts/MultisigWallet.sol

@@ -25,19 +25,19 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
    * @param _owners A list of owners.
    * @param _owners A list of owners.
    * @param _required The amount required for a transaction to be approved.
    * @param _required The amount required for a transaction to be approved.
    */
    */
-  function MultisigWallet(address[] _owners, uint256 _required, uint256 _daylimit)       
-    Shareable(_owners, _required)        
+  function MultisigWallet(address[] _owners, uint256 _required, uint256 _daylimit)
+    Shareable(_owners, _required)
     DayLimit(_daylimit) { }
     DayLimit(_daylimit) { }
 
 
-  /** 
-   * @dev destroys the contract sending everything to `_to`. 
+  /**
+   * @dev destroys the contract sending everything to `_to`.
    */
    */
   function destroy(address _to) onlymanyowners(keccak256(msg.data)) external {
   function destroy(address _to) onlymanyowners(keccak256(msg.data)) external {
     selfdestruct(_to);
     selfdestruct(_to);
   }
   }
 
 
-  /** 
-   * @dev Fallback function, receives value and emits a deposit event. 
+  /**
+   * @dev Fallback function, receives value and emits a deposit event.
    */
    */
   function() payable {
   function() payable {
     // just being sent some cash?
     // just being sent some cash?
@@ -46,10 +46,10 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
   }
   }
 
 
   /**
   /**
-   * @dev Outside-visible transaction entry point. Executes transaction immediately if below daily 
-   * spending limit. If not, goes into multisig process. We provide a hash on return to allow the 
-   * sender to provide shortcuts for the other confirmations (allowing them to avoid replicating 
-   * the _to, _value, and _data arguments). They still get the option of using them if they want, 
+   * @dev Outside-visible transaction entry point. Executes transaction immediately if below daily
+   * spending limit. If not, goes into multisig process. We provide a hash on return to allow the
+   * sender to provide shortcuts for the other confirmations (allowing them to avoid replicating
+   * the _to, _value, and _data arguments). They still get the option of using them if they want,
    * anyways.
    * anyways.
    * @param _to The receiver address
    * @param _to The receiver address
    * @param _value The value to send
    * @param _value The value to send
@@ -61,7 +61,7 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
       SingleTransact(msg.sender, _value, _to, _data);
       SingleTransact(msg.sender, _value, _to, _data);
       // yes - just execute the call.
       // yes - just execute the call.
       if (!_to.call.value(_value)(_data)) {
       if (!_to.call.value(_value)(_data)) {
-        throw;
+        revert();
       }
       }
       return 0;
       return 0;
     }
     }
@@ -76,30 +76,28 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
   }
   }
 
 
   /**
   /**
-   * @dev Confirm a transaction by providing just the hash. We use the previous transactions map, 
+   * @dev Confirm a transaction by providing just the hash. We use the previous transactions map,
    * txs, in order to determine the body of the transaction from the hash provided.
    * txs, in order to determine the body of the transaction from the hash provided.
    * @param _h The transaction hash to approve.
    * @param _h The transaction hash to approve.
    */
    */
   function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) {
   function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) {
     if (txs[_h].to != 0) {
     if (txs[_h].to != 0) {
-      if (!txs[_h].to.call.value(txs[_h].value)(txs[_h].data)) {
-        throw;
-      }
+      assert(txs[_h].to.call.value(txs[_h].value)(txs[_h].data));
       MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data);
       MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data);
       delete txs[_h];
       delete txs[_h];
       return true;
       return true;
     }
     }
   }
   }
 
 
-  /** 
-   * @dev Updates the daily limit value. 
+  /**
+   * @dev Updates the daily limit value.
    * @param _newLimit  uint256 to represent the new limit.
    * @param _newLimit  uint256 to represent the new limit.
    */
    */
   function setDailyLimit(uint256 _newLimit) onlymanyowners(keccak256(msg.data)) external {
   function setDailyLimit(uint256 _newLimit) onlymanyowners(keccak256(msg.data)) external {
     _setDailyLimit(_newLimit);
     _setDailyLimit(_newLimit);
   }
   }
 
 
-  /** 
+  /**
    * @dev Resets the value spent to enable more spending
    * @dev Resets the value spent to enable more spending
    */
    */
   function resetSpentToday() onlymanyowners(keccak256(msg.data)) external {
   function resetSpentToday() onlymanyowners(keccak256(msg.data)) external {
@@ -108,7 +106,7 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
 
 
 
 
   // INTERNAL METHODS
   // INTERNAL METHODS
-  /** 
+  /**
    * @dev Clears the list of transactions pending approval.
    * @dev Clears the list of transactions pending approval.
    */
    */
   function clearPending() internal {
   function clearPending() internal {

+ 5 - 8
contracts/ReentrancyGuard.sol

@@ -9,7 +9,7 @@ pragma solidity ^0.4.11;
 contract ReentrancyGuard {
 contract ReentrancyGuard {
 
 
   /**
   /**
-   * @dev We use a single lock for the whole contract. 
+   * @dev We use a single lock for the whole contract.
    */
    */
   bool private rentrancy_lock = false;
   bool private rentrancy_lock = false;
 
 
@@ -22,13 +22,10 @@ contract ReentrancyGuard {
    * wrapper marked as `nonReentrant`.
    * wrapper marked as `nonReentrant`.
    */
    */
   modifier nonReentrant() {
   modifier nonReentrant() {
-    if(rentrancy_lock == false) {
-      rentrancy_lock = true;
-      _;
-      rentrancy_lock = false;
-    } else {
-      throw;
-    }
+    require(!rentrancy_lock);
+    rentrancy_lock = true;
+    _;
+    rentrancy_lock = false;
   }
   }
 
 
 }
 }

+ 0 - 48
contracts/SafeMath.sol

@@ -1,48 +0,0 @@
-pragma solidity ^0.4.11;
-
-
-/**
- * Math operations with safety checks
- */
-library SafeMath {
-  function mul(uint256 a, uint256 b) internal returns (uint256) {
-    uint256 c = a * b;
-    assert(a == 0 || c / a == b);
-    return c;
-  }
-
-  function div(uint256 a, uint256 b) internal returns (uint256) {
-    // assert(b > 0); // Solidity automatically throws when dividing by 0
-    uint256 c = a / b;
-    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
-    return c;
-  }
-
-  function sub(uint256 a, uint256 b) internal returns (uint256) {
-    assert(b <= a);
-    return a - b;
-  }
-
-  function add(uint256 a, uint256 b) internal returns (uint256) {
-    uint256 c = a + b;
-    assert(c >= a);
-    return c;
-  }
-
-  function max64(uint64 a, uint64 b) internal constant returns (uint64) {
-    return a >= b ? a : b;
-  }
-
-  function min64(uint64 a, uint64 b) internal constant returns (uint64) {
-    return a < b ? a : b;
-  }
-
-  function max256(uint256 a, uint256 b) internal constant returns (uint256) {
-    return a >= b ? a : b;
-  }
-
-  function min256(uint256 a, uint256 b) internal constant returns (uint256) {
-    return a < b ? a : b;
-  }
-
-}

+ 34 - 0
contracts/crowdsale/CappedCrowdsale.sol

@@ -0,0 +1,34 @@
+pragma solidity ^0.4.11;
+
+import '../math/SafeMath.sol';
+import './Crowdsale.sol';
+
+/**
+ * @title CappedCrowdsale
+ * @dev Extension of Crowsdale with a max amount of funds raised
+ */
+contract CappedCrowdsale is Crowdsale {
+  using SafeMath for uint256;
+
+  uint256 public cap;
+
+  function CappedCrowdsale(uint256 _cap) {
+    require(_cap > 0);
+    cap = _cap;
+  }
+
+  // overriding Crowdsale#validPurchase to add extra cap logic
+  // @return true if investors can buy at the moment
+  function validPurchase() internal constant returns (bool) {
+    bool withinCap = weiRaised.add(msg.value) <= cap;
+    return super.validPurchase() && withinCap;
+  }
+
+  // overriding Crowdsale#hasEnded to add cap logic
+  // @return true if crowdsale event has ended
+  function hasEnded() public constant returns (bool) {
+    bool capReached = weiRaised >= cap;
+    return super.hasEnded() || capReached;
+  }
+
+}

+ 107 - 0
contracts/crowdsale/Crowdsale.sol

@@ -0,0 +1,107 @@
+pragma solidity ^0.4.11;
+
+import '../token/MintableToken.sol';
+import '../math/SafeMath.sol';
+
+/**
+ * @title Crowdsale 
+ * @dev Crowdsale is a base contract for managing a token crowdsale.
+ * Crowdsales have a start and end block, where investors can make
+ * token purchases and the crowdsale will assign them tokens based
+ * on a token per ETH rate. Funds collected are forwarded to a wallet 
+ * as they arrive.
+ */
+contract Crowdsale {
+  using SafeMath for uint256;
+
+  // The token being sold
+  MintableToken public token;
+
+  // start and end block where investments are allowed (both inclusive)
+  uint256 public startBlock;
+  uint256 public endBlock;
+
+  // address where funds are collected
+  address public wallet;
+
+  // how many token units a buyer gets per wei
+  uint256 public rate;
+
+  // amount of raised money in wei
+  uint256 public weiRaised;
+
+  /**
+   * event for token purchase logging
+   * @param purchaser who paid for the tokens
+   * @param beneficiary who got the tokens
+   * @param value weis paid for purchase
+   * @param amount amount of tokens purchased
+   */ 
+  event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
+
+
+  function Crowdsale(uint256 _startBlock, uint256 _endBlock, uint256 _rate, address _wallet) {
+    require(_startBlock >= block.number);
+    require(_endBlock >= _startBlock);
+    require(_rate > 0);
+    require(_wallet != 0x0);
+
+    token = createTokenContract();
+    startBlock = _startBlock;
+    endBlock = _endBlock;
+    rate = _rate;
+    wallet = _wallet;
+  }
+
+  // creates the token to be sold. 
+  // override this method to have crowdsale of a specific mintable token.
+  function createTokenContract() internal returns (MintableToken) {
+    return new MintableToken();
+  }
+
+
+  // fallback function can be used to buy tokens
+  function () payable {
+    buyTokens(msg.sender);
+  }
+
+  // low level token purchase function
+  function buyTokens(address beneficiary) payable {
+    require(beneficiary != 0x0);
+    require(validPurchase());
+
+    uint256 weiAmount = msg.value;
+
+    // calculate token amount to be created
+    uint256 tokens = weiAmount.mul(rate);
+
+    // update state
+    weiRaised = weiRaised.add(weiAmount);
+
+    token.mint(beneficiary, tokens);
+    TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
+
+    forwardFunds();
+  }
+
+  // send ether to the fund collection wallet
+  // override to create custom fund forwarding mechanisms
+  function forwardFunds() internal {
+    wallet.transfer(msg.value);
+  }
+
+  // @return true if the transaction can buy tokens
+  function validPurchase() internal constant returns (bool) {
+    uint256 current = block.number;
+    bool withinPeriod = current >= startBlock && current <= endBlock;
+    bool nonZeroPurchase = msg.value != 0;
+    return withinPeriod && nonZeroPurchase;
+  }
+
+  // @return true if crowdsale event has ended
+  function hasEnded() public constant returns (bool) {
+    return block.number > endBlock;
+  }
+
+
+}

+ 39 - 0
contracts/crowdsale/FinalizableCrowdsale.sol

@@ -0,0 +1,39 @@
+pragma solidity ^0.4.11;
+
+import '../math/SafeMath.sol';
+import '../ownership/Ownable.sol';
+import './Crowdsale.sol';
+
+/**
+ * @title FinalizableCrowdsale
+ * @dev Extension of Crowsdale where an owner can do extra work
+ * after finishing. By default, it will end token minting.
+ */
+contract FinalizableCrowdsale is Crowdsale, Ownable {
+  using SafeMath for uint256;
+
+  bool public isFinalized = false;
+
+  event Finalized();
+
+  // should be called after crowdsale ends, to do
+  // some extra finalization work
+  function finalize() onlyOwner {
+    require(!isFinalized);
+    require(hasEnded());
+
+    finalization();
+    Finalized();
+    
+    isFinalized = true;
+  }
+
+  // end token minting on finalization
+  // override this with custom logic if needed
+  function finalization() internal {
+    token.finishMinting();
+  }
+
+
+
+}

+ 56 - 0
contracts/crowdsale/RefundVault.sol

@@ -0,0 +1,56 @@
+pragma solidity ^0.4.11;
+
+import '../math/SafeMath.sol';
+import '../ownership/Ownable.sol';
+
+/**
+ * @title RefundVault
+ * @dev This contract is used for storing funds while a crowdsale
+ * is in progress. Supports refunding the money if crowdsale fails,
+ * and forwarding it if crowdsale is successful.
+ */
+contract RefundVault is Ownable {
+  using SafeMath for uint256;
+
+  enum State { Active, Refunding, Closed }
+
+  mapping (address => uint256) public deposited;
+  address public wallet;
+  State public state;
+
+  event Closed();
+  event RefundsEnabled();
+  event Refunded(address indexed beneficiary, uint256 weiAmount);
+
+  function RefundVault(address _wallet) {
+    require(_wallet != 0x0);
+    wallet = _wallet;
+    state = State.Active;
+  }
+
+  function deposit(address investor) onlyOwner payable {
+    require(state == State.Active);
+    deposited[investor] = deposited[investor].add(msg.value);
+  }
+
+  function close() onlyOwner {
+    require(state == State.Active);
+    state = State.Closed;
+    Closed();
+    wallet.transfer(this.balance);
+  }
+
+  function enableRefunds() onlyOwner {
+    require(state == State.Active);
+    state = State.Refunding;
+    RefundsEnabled();
+  }
+
+  function refund(address investor) {
+    require(state == State.Refunding);
+    uint256 depositedValue = deposited[investor];
+    deposited[investor] = 0;
+    investor.transfer(depositedValue);
+    Refunded(investor, depositedValue);
+  }
+}

+ 60 - 0
contracts/crowdsale/RefundableCrowdsale.sol

@@ -0,0 +1,60 @@
+pragma solidity ^0.4.11;
+
+
+import '../math/SafeMath.sol';
+import './FinalizableCrowdsale.sol';
+import './RefundVault.sol';
+
+
+/**
+ * @title RefundableCrowdsale
+ * @dev Extension of Crowdsale contract that adds a funding goal, and
+ * the possibility of users getting a refund if goal is not met.
+ * Uses a RefundVault as the crowdsale's vault.
+ */
+contract RefundableCrowdsale is FinalizableCrowdsale {
+  using SafeMath for uint256;
+
+  // minimum amount of funds to be raised in weis
+  uint256 public goal;
+
+  // refund vault used to hold funds while crowdsale is running
+  RefundVault public vault;
+
+  function RefundableCrowdsale(uint256 _goal) {
+    require(_goal > 0);
+    vault = new RefundVault(wallet);
+    goal = _goal;
+  }
+
+  // We're overriding the fund forwarding from Crowdsale.
+  // In addition to sending the funds, we want to call
+  // the RefundVault deposit function
+  function forwardFunds() internal {
+    vault.deposit.value(msg.value)(msg.sender);
+  }
+
+  // if crowdsale is unsuccessful, investors can claim refunds here
+  function claimRefund() {
+    require(isFinalized);
+    require(!goalReached());
+
+    vault.refund(msg.sender);
+  }
+
+  // vault finalization task, called when owner calls finalize()
+  function finalization() internal {
+    if (goalReached()) {
+      vault.close();
+    } else {
+      vault.enableRefunds();
+    }
+
+    super.finalization();
+  }
+
+  function goalReached() public constant returns (bool) {
+    return weiRaised >= goal;
+  }
+
+}

+ 2 - 2
contracts/lifecycle/Pausable.sol

@@ -19,7 +19,7 @@ contract Pausable is Ownable {
    * @dev modifier to allow actions only when the contract IS paused
    * @dev modifier to allow actions only when the contract IS paused
    */
    */
   modifier whenNotPaused() {
   modifier whenNotPaused() {
-    if (paused) throw;
+    require(!paused);
     _;
     _;
   }
   }
 
 
@@ -27,7 +27,7 @@ contract Pausable is Ownable {
    * @dev modifier to allow actions only when the contract IS NOT paused
    * @dev modifier to allow actions only when the contract IS NOT paused
    */
    */
   modifier whenPaused {
   modifier whenPaused {
-    if (!paused) throw;
+    require(paused);
     _;
     _;
   }
   }
 
 

+ 24 - 0
contracts/math/Math.sol

@@ -0,0 +1,24 @@
+pragma solidity ^0.4.11;
+
+/**
+ * @title Math
+ * @dev Assorted math operations
+ */
+
+library Math {
+  function max64(uint64 a, uint64 b) internal constant returns (uint64) {
+    return a >= b ? a : b;
+  }
+
+  function min64(uint64 a, uint64 b) internal constant returns (uint64) {
+    return a < b ? a : b;
+  }
+
+  function max256(uint256 a, uint256 b) internal constant returns (uint256) {
+    return a >= b ? a : b;
+  }
+
+  function min256(uint256 a, uint256 b) internal constant returns (uint256) {
+    return a < b ? a : b;
+  }
+}

+ 32 - 0
contracts/math/SafeMath.sol

@@ -0,0 +1,32 @@
+pragma solidity ^0.4.11;
+
+
+/**
+ * @title SafeMath
+ * @dev Math operations with safety checks that throw on error
+ */
+library SafeMath {
+  function mul(uint256 a, uint256 b) internal constant returns (uint256) {
+    uint256 c = a * b;
+    assert(a == 0 || c / a == b);
+    return c;
+  }
+
+  function div(uint256 a, uint256 b) internal constant returns (uint256) {
+    // assert(b > 0); // Solidity automatically throws when dividing by 0
+    uint256 c = a / b;
+    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
+    return c;
+  }
+
+  function sub(uint256 a, uint256 b) internal constant returns (uint256) {
+    assert(b <= a);
+    return a - b;
+  }
+
+  function add(uint256 a, uint256 b) internal constant returns (uint256) {
+    uint256 c = a + b;
+    assert(c >= a);
+    return c;
+  }
+}

+ 5 - 7
contracts/ownership/Claimable.sol

@@ -6,25 +6,23 @@ import './Ownable.sol';
 
 
 /**
 /**
  * @title Claimable
  * @title Claimable
- * @dev Extension for the Ownable contract, where the ownership needs to be claimed. 
+ * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
  * This allows the new owner to accept the transfer.
  * This allows the new owner to accept the transfer.
  */
  */
 contract Claimable is Ownable {
 contract Claimable is Ownable {
   address public pendingOwner;
   address public pendingOwner;
 
 
   /**
   /**
-   * @dev Modifier throws if called by any account other than the pendingOwner. 
+   * @dev Modifier throws if called by any account other than the pendingOwner.
    */
    */
   modifier onlyPendingOwner() {
   modifier onlyPendingOwner() {
-    if (msg.sender != pendingOwner) {
-      throw;
-    }
+    require(msg.sender == pendingOwner);
     _;
     _;
   }
   }
 
 
   /**
   /**
-   * @dev Allows the current owner to set the pendingOwner address. 
-   * @param newOwner The address to transfer ownership to. 
+   * @dev Allows the current owner to set the pendingOwner address.
+   * @param newOwner The address to transfer ownership to.
    */
    */
   function transferOwnership(address newOwner) onlyOwner {
   function transferOwnership(address newOwner) onlyOwner {
     pendingOwner = newOwner;
     pendingOwner = newOwner;

+ 7 - 9
contracts/ownership/DelayedClaimable.sol

@@ -15,26 +15,24 @@ contract DelayedClaimable is Claimable {
   uint256 public start;
   uint256 public start;
 
 
   /**
   /**
-   * @dev Used to specify the time period during which a pending 
-   * owner can claim ownership. 
+   * @dev Used to specify the time period during which a pending
+   * owner can claim ownership.
    * @param _start The earliest time ownership can be claimed.
    * @param _start The earliest time ownership can be claimed.
-   * @param _end The latest time ownership can be claimed. 
+   * @param _end The latest time ownership can be claimed.
    */
    */
   function setLimits(uint256 _start, uint256 _end) onlyOwner {
   function setLimits(uint256 _start, uint256 _end) onlyOwner {
-    if (_start > _end)
-        throw;
+    require(_start <= _end);
     end = _end;
     end = _end;
     start = _start;
     start = _start;
   }
   }
 
 
 
 
   /**
   /**
-   * @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within 
-   * the specified start and end time. 
+   * @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within
+   * the specified start and end time.
    */
    */
   function claimOwnership() onlyPendingOwner {
   function claimOwnership() onlyPendingOwner {
-    if ((block.number > end) || (block.number < start))
-        throw;
+    require((block.number <= end) && (block.number >= start));
     owner = pendingOwner;
     owner = pendingOwner;
     pendingOwner = 0x0;
     pendingOwner = 0x0;
     end = 0;
     end = 0;

+ 6 - 10
contracts/ownership/HasNoEther.sol

@@ -2,7 +2,7 @@ pragma solidity ^0.4.11;
 
 
 import "./Ownable.sol";
 import "./Ownable.sol";
 
 
-/** 
+/**
  * @title Contracts that should not own Ether
  * @title Contracts that should not own Ether
  * @author Remco Bloemen <remco@2π.com>
  * @author Remco Bloemen <remco@2π.com>
  * @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up
  * @dev This tries to block incoming ether to prevent accidental loss of Ether. Should Ether end up
@@ -16,15 +16,13 @@ contract HasNoEther is Ownable {
 
 
   /**
   /**
   * @dev Constructor that rejects incoming Ether
   * @dev Constructor that rejects incoming Ether
-  * @dev The `payable` flag is added so we can access `msg.value` without compiler warning. If we 
-  * leave out payable, then Solidity will allow inheriting contracts to implement a payable 
-  * constructor. By doing it this way we prevent a payable constructor from working. Alternatively 
+  * @dev The `payable` flag is added so we can access `msg.value` without compiler warning. If we
+  * leave out payable, then Solidity will allow inheriting contracts to implement a payable
+  * constructor. By doing it this way we prevent a payable constructor from working. Alternatively
   * we could use assembly to access msg.value.
   * we could use assembly to access msg.value.
   */
   */
   function HasNoEther() payable {
   function HasNoEther() payable {
-    if(msg.value > 0) {
-      throw;
-    }
+    require(msg.value == 0);
   }
   }
 
 
   /**
   /**
@@ -37,8 +35,6 @@ contract HasNoEther is Ownable {
    * @dev Transfer all Ether held by the contract to the owner.
    * @dev Transfer all Ether held by the contract to the owner.
    */
    */
   function reclaimEther() external onlyOwner {
   function reclaimEther() external onlyOwner {
-    if(!owner.send(this.balance)) {
-      throw;
-    }
+    assert(owner.send(this.balance));
   }
   }
 }
 }

+ 3 - 3
contracts/ownership/HasNoTokens.sol

@@ -3,7 +3,7 @@ pragma solidity ^0.4.11;
 import "./Ownable.sol";
 import "./Ownable.sol";
 import "../token/ERC20Basic.sol";
 import "../token/ERC20Basic.sol";
 
 
-/** 
+/**
  * @title Contracts that should not own Tokens
  * @title Contracts that should not own Tokens
  * @author Remco Bloemen <remco@2π.com>
  * @author Remco Bloemen <remco@2π.com>
  * @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
  * @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
@@ -12,14 +12,14 @@ import "../token/ERC20Basic.sol";
  */
  */
 contract HasNoTokens is Ownable {
 contract HasNoTokens is Ownable {
 
 
- /** 
+ /**
   * @dev Reject all ERC23 compatible tokens
   * @dev Reject all ERC23 compatible tokens
   * @param from_ address The address that is transferring the tokens
   * @param from_ address The address that is transferring the tokens
   * @param value_ uint256 the amount of the specified token
   * @param value_ uint256 the amount of the specified token
   * @param data_ Bytes The data passed from the caller.
   * @param data_ Bytes The data passed from the caller.
   */
   */
   function tokenFallback(address from_, uint256 value_, bytes data_) external {
   function tokenFallback(address from_, uint256 value_, bytes data_) external {
-    throw;
+    revert();
   }
   }
 
 
   /**
   /**

+ 6 - 8
contracts/ownership/Ownable.sol

@@ -3,14 +3,14 @@ pragma solidity ^0.4.11;
 
 
 /**
 /**
  * @title Ownable
  * @title Ownable
- * @dev The Ownable contract has an owner address, and provides basic authorization control 
- * functions, this simplifies the implementation of "user permissions". 
+ * @dev The Ownable contract has an owner address, and provides basic authorization control
+ * functions, this simplifies the implementation of "user permissions".
  */
  */
 contract Ownable {
 contract Ownable {
   address public owner;
   address public owner;
 
 
 
 
-  /** 
+  /**
    * @dev The Ownable constructor sets the original `owner` of the contract to the sender
    * @dev The Ownable constructor sets the original `owner` of the contract to the sender
    * account.
    * account.
    */
    */
@@ -20,19 +20,17 @@ contract Ownable {
 
 
 
 
   /**
   /**
-   * @dev Throws if called by any account other than the owner. 
+   * @dev Throws if called by any account other than the owner.
    */
    */
   modifier onlyOwner() {
   modifier onlyOwner() {
-    if (msg.sender != owner) {
-      throw;
-    }
+    require(msg.sender == owner);
     _;
     _;
   }
   }
 
 
 
 
   /**
   /**
    * @dev Allows the current owner to transfer control of the contract to a newOwner.
    * @dev Allows the current owner to transfer control of the contract to a newOwner.
-   * @param newOwner The address to transfer ownership to. 
+   * @param newOwner The address to transfer ownership to.
    */
    */
   function transferOwnership(address newOwner) onlyOwner {
   function transferOwnership(address newOwner) onlyOwner {
     if (newOwner != address(0)) {
     if (newOwner != address(0)) {

+ 9 - 15
contracts/ownership/Shareable.sol

@@ -3,7 +3,7 @@ pragma solidity ^0.4.11;
 
 
 /**
 /**
  * @title Shareable
  * @title Shareable
- * @dev inheritable "property" contract that enables methods to be protected by requiring the 
+ * @dev inheritable "property" contract that enables methods to be protected by requiring the
  * acquiescence of either a single, or, crucially, each of a number of, designated owners.
  * acquiescence of either a single, or, crucially, each of a number of, designated owners.
  * @dev Usage: use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by some number (specified in constructor) of the set of owners (specified in the constructor) before the interior is executed.
  * @dev Usage: use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by some number (specified in constructor) of the set of owners (specified in the constructor) before the interior is executed.
  */
  */
@@ -36,14 +36,12 @@ contract Shareable {
 
 
   // simple single-sig function modifier.
   // simple single-sig function modifier.
   modifier onlyOwner {
   modifier onlyOwner {
-    if (!isOwner(msg.sender)) {
-      throw;
-    }
+    require(isOwner(msg.sender));
     _;
     _;
   }
   }
-  
-  /** 
-   * @dev Modifier for multisig functions. 
+
+  /**
+   * @dev Modifier for multisig functions.
    * @param _operation The operation must have an intrinsic hash in order that later attempts can be
    * @param _operation The operation must have an intrinsic hash in order that later attempts can be
    * realised as the same underlying operation and thus count as confirmations.
    * realised as the same underlying operation and thus count as confirmations.
    */
    */
@@ -53,8 +51,8 @@ contract Shareable {
     }
     }
   }
   }
 
 
-  /** 
-   * @dev Constructor is given the number of sigs required to do protected "onlymanyowners" 
+  /**
+   * @dev Constructor is given the number of sigs required to do protected "onlymanyowners"
    * transactions as well as the selection of addresses capable of confirming them.
    * transactions as well as the selection of addresses capable of confirming them.
    * @param _owners A list of owners.
    * @param _owners A list of owners.
    * @param _required The amount required for a transaction to be approved.
    * @param _required The amount required for a transaction to be approved.
@@ -67,9 +65,7 @@ contract Shareable {
       ownerIndex[_owners[i]] = 2 + i;
       ownerIndex[_owners[i]] = 2 + i;
     }
     }
     required = _required;
     required = _required;
-    if (required > owners.length) {
-      throw;
-    }
+    require(required <= owners.length);
   }
   }
 
 
   /**
   /**
@@ -138,9 +134,7 @@ contract Shareable {
     // determine what index the present sender is:
     // determine what index the present sender is:
     uint256 index = ownerIndex[msg.sender];
     uint256 index = ownerIndex[msg.sender];
     // make sure they're an owner
     // make sure they're an owner
-    if (index == 0) {
-      throw;
-    }
+    require(index != 0);
 
 
     var pending = pendings[_operation];
     var pending = pendings[_operation];
     // if we're not yet working on this operation, switch over and reset the confirmation status.
     // if we're not yet working on this operation, switch over and reset the confirmation status.

+ 4 - 11
contracts/payment/PullPayment.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.11;
 pragma solidity ^0.4.11;
 
 
 
 
-import '../SafeMath.sol';
+import '../math/SafeMath.sol';
 
 
 
 
 /**
 /**
@@ -32,19 +32,12 @@ contract PullPayment {
     address payee = msg.sender;
     address payee = msg.sender;
     uint256 payment = payments[payee];
     uint256 payment = payments[payee];
 
 
-    if (payment == 0) {
-      throw;
-    }
-
-    if (this.balance < payment) {
-      throw;
-    }
+    require(payment != 0);
+    require(this.balance >= payment);
 
 
     totalPayments = totalPayments.sub(payment);
     totalPayments = totalPayments.sub(payment);
     payments[payee] = 0;
     payments[payee] = 0;
 
 
-    if (!payee.send(payment)) {
-      throw;
-    }
+    assert(payee.send(payment));
   }
   }
 }
 }

+ 3 - 2
contracts/token/BasicToken.sol

@@ -2,7 +2,7 @@ pragma solidity ^0.4.11;
 
 
 
 
 import './ERC20Basic.sol';
 import './ERC20Basic.sol';
-import '../SafeMath.sol';
+import '../math/SafeMath.sol';
 
 
 
 
 /**
 /**
@@ -19,10 +19,11 @@ contract BasicToken is ERC20Basic {
   * @param _to The address to transfer to.
   * @param _to The address to transfer to.
   * @param _value The amount to be transferred.
   * @param _value The amount to be transferred.
   */
   */
-  function transfer(address _to, uint256 _value) {
+  function transfer(address _to, uint256 _value) returns (bool) {
     balances[msg.sender] = balances[msg.sender].sub(_value);
     balances[msg.sender] = balances[msg.sender].sub(_value);
     balances[_to] = balances[_to].add(_value);
     balances[_to] = balances[_to].add(_value);
     Transfer(msg.sender, _to, _value);
     Transfer(msg.sender, _to, _value);
+    return true;
   }
   }
 
 
   /**
   /**

+ 0 - 60
contracts/token/CrowdsaleToken.sol

@@ -1,60 +0,0 @@
-pragma solidity ^0.4.11;
-
-
-import "./StandardToken.sol";
-
-
-/**
- * @title CrowdsaleToken
- *
- * @dev Simple ERC20 Token example, with crowdsale token creation
- * @dev IMPORTANT NOTE: do not use or deploy this contract as-is. It needs some changes to be 
- * production ready.
- */
-contract CrowdsaleToken is StandardToken {
-
-  string public constant name = "CrowdsaleToken";
-  string public constant symbol = "CRW";
-  uint256 public constant decimals = 18;
-  // replace with your fund collection multisig address
-  address public constant multisig = 0x0;
-
-
-  // 1 ether = 500 example tokens
-  uint256 public constant PRICE = 500;
-
-  /**
-   * @dev Fallback function which receives ether and sends the appropriate number of tokens to the 
-   * msg.sender.
-   */
-  function () payable {
-    createTokens(msg.sender);
-  }
-
-  /**
-   * @dev Creates tokens and send to the specified address.
-   * @param recipient The address which will recieve the new tokens.
-   */
-  function createTokens(address recipient) payable {
-    if (msg.value == 0) {
-      throw;
-    }
-
-    uint256 tokens = msg.value.mul(getPrice());
-    totalSupply = totalSupply.add(tokens);
-
-    balances[recipient] = balances[recipient].add(tokens);
-
-    if (!multisig.send(msg.value)) {
-      throw;
-    }
-  }
-
-  /**
-   * @dev replace this with any other price function
-   * @return The price per unit of token. 
-   */
-  function getPrice() constant returns (uint256 result) {
-    return PRICE;
-  }
-}

+ 2 - 2
contracts/token/ERC20.sol

@@ -10,7 +10,7 @@ import './ERC20Basic.sol';
  */
  */
 contract ERC20 is ERC20Basic {
 contract ERC20 is ERC20Basic {
   function allowance(address owner, address spender) constant returns (uint256);
   function allowance(address owner, address spender) constant returns (uint256);
-  function transferFrom(address from, address to, uint256 value);
-  function approve(address spender, uint256 value);
+  function transferFrom(address from, address to, uint256 value) returns (bool);
+  function approve(address spender, uint256 value) returns (bool);
   event Approval(address indexed owner, address indexed spender, uint256 value);
   event Approval(address indexed owner, address indexed spender, uint256 value);
 }
 }

+ 2 - 2
contracts/token/ERC20Basic.sol

@@ -4,11 +4,11 @@ pragma solidity ^0.4.11;
 /**
 /**
  * @title ERC20Basic
  * @title ERC20Basic
  * @dev Simpler version of ERC20 interface
  * @dev Simpler version of ERC20 interface
- * @dev see https://github.com/ethereum/EIPs/issues/20
+ * @dev see https://github.com/ethereum/EIPs/issues/179
  */
  */
 contract ERC20Basic {
 contract ERC20Basic {
   uint256 public totalSupply;
   uint256 public totalSupply;
   function balanceOf(address who) constant returns (uint256);
   function balanceOf(address who) constant returns (uint256);
-  function transfer(address to, uint256 value);
+  function transfer(address to, uint256 value) returns (bool);
   event Transfer(address indexed from, address indexed to, uint256 value);
   event Transfer(address indexed from, address indexed to, uint256 value);
 }
 }

+ 10 - 10
contracts/token/LimitedTransferToken.sol

@@ -4,11 +4,11 @@ import "./ERC20.sol";
 
 
 /**
 /**
  * @title LimitedTransferToken
  * @title LimitedTransferToken
- * @dev LimitedTransferToken defines the generic interface and the implementation to limit token 
- * transferability for different events. It is intended to be used as a base class for other token 
- * contracts. 
+ * @dev LimitedTransferToken defines the generic interface and the implementation to limit token
+ * transferability for different events. It is intended to be used as a base class for other token
+ * contracts.
  * LimitedTransferToken has been designed to allow for different limiting factors,
  * LimitedTransferToken has been designed to allow for different limiting factors,
- * this can be achieved by recursively calling super.transferableTokens() until the base class is 
+ * this can be achieved by recursively calling super.transferableTokens() until the base class is
  * hit. For example:
  * hit. For example:
  *     function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
  *     function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
  *       return min256(unlockedTokens, super.transferableTokens(holder, time));
  *       return min256(unlockedTokens, super.transferableTokens(holder, time));
@@ -23,7 +23,7 @@ contract LimitedTransferToken is ERC20 {
    * @dev Checks whether it can transfer or otherwise throws.
    * @dev Checks whether it can transfer or otherwise throws.
    */
    */
   modifier canTransfer(address _sender, uint256 _value) {
   modifier canTransfer(address _sender, uint256 _value) {
-   if (_value > transferableTokens(_sender, uint64(now))) throw;
+   require(_value <= transferableTokens(_sender, uint64(now)));
    _;
    _;
   }
   }
 
 
@@ -32,8 +32,8 @@ contract LimitedTransferToken is ERC20 {
    * @param _to The address that will recieve the tokens.
    * @param _to The address that will recieve the tokens.
    * @param _value The amount of tokens to be transferred.
    * @param _value The amount of tokens to be transferred.
    */
    */
-  function transfer(address _to, uint256 _value) canTransfer(msg.sender, _value) {
-    super.transfer(_to, _value);
+  function transfer(address _to, uint256 _value) canTransfer(msg.sender, _value) returns (bool) {
+    return super.transfer(_to, _value);
   }
   }
 
 
   /**
   /**
@@ -42,13 +42,13 @@ contract LimitedTransferToken is ERC20 {
   * @param _to The address that will recieve the tokens.
   * @param _to The address that will recieve the tokens.
   * @param _value The amount of tokens to be transferred.
   * @param _value The amount of tokens to be transferred.
   */
   */
-  function transferFrom(address _from, address _to, uint256 _value) canTransfer(_from, _value) {
-    super.transferFrom(_from, _to, _value);
+  function transferFrom(address _from, address _to, uint256 _value) canTransfer(_from, _value) returns (bool) {
+    return super.transferFrom(_from, _to, _value);
   }
   }
 
 
   /**
   /**
    * @dev Default transferable tokens function returns all tokens for a holder (no limit).
    * @dev Default transferable tokens function returns all tokens for a holder (no limit).
-   * @dev Overwriting transferableTokens(address holder, uint64 time) is the way to provide the 
+   * @dev Overwriting transferableTokens(address holder, uint64 time) is the way to provide the
    * specific logic for limiting token transferability for a holder over time.
    * specific logic for limiting token transferability for a holder over time.
    */
    */
   function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
   function transferableTokens(address holder, uint64 time) constant public returns (uint256) {

+ 1 - 1
contracts/token/MintableToken.sol

@@ -21,7 +21,7 @@ contract MintableToken is StandardToken, Ownable {
 
 
 
 
   modifier canMint() {
   modifier canMint() {
-    if(mintingFinished) throw;
+    require(!mintingFinished);
     _;
     _;
   }
   }
 
 

+ 5 - 9
contracts/token/PausableToken.sol

@@ -7,19 +7,15 @@ import '../lifecycle/Pausable.sol';
  * Pausable token
  * Pausable token
  *
  *
  * Simple ERC20 Token example, with pausable token creation
  * Simple ERC20 Token example, with pausable token creation
- * Issue:
- * https://github.com/OpenZeppelin/zeppelin-solidity/issues/194
- * Based on code by BCAPtoken:
- * https://github.com/BCAPtoken/BCAPToken/blob/5cb5e76338cc47343ba9268663a915337c8b268e/sol/BCAPToken.sol#L27
  **/
  **/
 
 
-contract PausableToken is Pausable, StandardToken {
+contract PausableToken is StandardToken, Pausable {
 
 
-  function transfer(address _to, uint256 _value) whenNotPaused {
-    super.transfer(_to, _value);
+  function transfer(address _to, uint256 _value) whenNotPaused returns (bool) {
+    return super.transfer(_to, _value);
   }
   }
 
 
-  function transferFrom(address _from, address _to, uint256 _value) whenNotPaused {
-    super.transferFrom(_from, _to, _value);
+  function transferFrom(address _from, address _to, uint256 _value) whenNotPaused returns (bool) {
+    return super.transferFrom(_from, _to, _value);
   }
   }
 }
 }

+ 8 - 6
contracts/token/StandardToken.sol

@@ -8,11 +8,11 @@ import './ERC20.sol';
 /**
 /**
  * @title Standard ERC20 token
  * @title Standard ERC20 token
  *
  *
- * @dev Implemantation of the basic standard token.
+ * @dev Implementation of the basic standard token.
  * @dev https://github.com/ethereum/EIPs/issues/20
  * @dev https://github.com/ethereum/EIPs/issues/20
  * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
  * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
  */
  */
-contract StandardToken is BasicToken, ERC20 {
+contract StandardToken is ERC20, BasicToken {
 
 
   mapping (address => mapping (address => uint256)) allowed;
   mapping (address => mapping (address => uint256)) allowed;
 
 
@@ -23,16 +23,17 @@ contract StandardToken is BasicToken, ERC20 {
    * @param _to address The address which you want to transfer to
    * @param _to address The address which you want to transfer to
    * @param _value uint256 the amout of tokens to be transfered
    * @param _value uint256 the amout of tokens to be transfered
    */
    */
-  function transferFrom(address _from, address _to, uint256 _value) {
+  function transferFrom(address _from, address _to, uint256 _value) returns (bool) {
     var _allowance = allowed[_from][msg.sender];
     var _allowance = allowed[_from][msg.sender];
 
 
     // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
     // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
-    // if (_value > _allowance) throw;
+    // require (_value <= _allowance);
 
 
     balances[_to] = balances[_to].add(_value);
     balances[_to] = balances[_to].add(_value);
     balances[_from] = balances[_from].sub(_value);
     balances[_from] = balances[_from].sub(_value);
     allowed[_from][msg.sender] = _allowance.sub(_value);
     allowed[_from][msg.sender] = _allowance.sub(_value);
     Transfer(_from, _to, _value);
     Transfer(_from, _to, _value);
+    return true;
   }
   }
 
 
   /**
   /**
@@ -40,16 +41,17 @@ contract StandardToken is BasicToken, ERC20 {
    * @param _spender The address which will spend the funds.
    * @param _spender The address which will spend the funds.
    * @param _value The amount of tokens to be spent.
    * @param _value The amount of tokens to be spent.
    */
    */
-  function approve(address _spender, uint256 _value) {
+  function approve(address _spender, uint256 _value) returns (bool) {
 
 
     // To change the approve amount you first have to reduce the addresses`
     // To change the approve amount you first have to reduce the addresses`
     //  allowance to zero by calling `approve(_spender, 0)` if it is not
     //  allowance to zero by calling `approve(_spender, 0)` if it is not
     //  already 0 to mitigate the race condition described here:
     //  already 0 to mitigate the race condition described here:
     //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
-    if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw;
+    require((_value == 0) || (allowed[msg.sender][_spender] == 0));
 
 
     allowed[msg.sender][_spender] = _value;
     allowed[msg.sender][_spender] = _value;
     Approval(msg.sender, _spender, _value);
     Approval(msg.sender, _spender, _value);
+    return true;
   }
   }
 
 
   /**
   /**

+ 49 - 0
contracts/token/TokenTimelock.sol

@@ -0,0 +1,49 @@
+pragma solidity ^0.4.11;
+
+
+import './ERC20Basic.sol';
+
+/**
+ * @title TokenTimelock
+ * @dev TokenTimelock is a token holder contract that will allow a
+ * beneficiary to extract the tokens after a given release time
+ */
+contract TokenTimelock {
+
+  // ERC20 basic token contract being held
+  ERC20Basic token;
+
+  // beneficiary of tokens after they are released
+  address beneficiary;
+
+  // timestamp when token release is enabled
+  uint64 releaseTime;
+
+  function TokenTimelock(ERC20Basic _token, address _beneficiary, uint64 _releaseTime) {
+    require(_releaseTime > now);
+    token = _token;
+    beneficiary = _beneficiary;
+    releaseTime = _releaseTime;
+  }
+
+  /**
+   * @notice Transfers tokens held by timelock to beneficiary.
+   * Deprecated: please use TokenTimelock#release instead.
+   */
+  function claim() {
+    require(msg.sender == beneficiary);
+    release();
+  }
+
+  /**
+   * @notice Transfers tokens held by timelock to beneficiary.
+   */
+  function release() {
+    require(now >= releaseTime);
+
+    uint256 amount = token.balanceOf(this);
+    require(amount > 0);
+
+    token.transfer(beneficiary, amount);
+  }
+}

+ 9 - 15
contracts/token/VestedToken.sol

@@ -1,5 +1,6 @@
 pragma solidity ^0.4.11;
 pragma solidity ^0.4.11;
 
 
+import "../math/Math.sol";
 import "./StandardToken.sol";
 import "./StandardToken.sol";
 import "./LimitedTransferToken.sol";
 import "./LimitedTransferToken.sol";
 
 
@@ -44,11 +45,9 @@ contract VestedToken is StandardToken, LimitedTransferToken {
   ) public {
   ) public {
 
 
     // Check for date inconsistencies that may cause unexpected behavior
     // Check for date inconsistencies that may cause unexpected behavior
-    if (_cliff < _start || _vesting < _cliff) {
-      throw;
-    }
+    require(_cliff >= _start && _vesting >= _cliff);
 
 
-    if (tokenGrantsCount(_to) > MAX_GRANTS_PER_ADDRESS) throw;   // To prevent a user being spammed and have his balance locked (out of gas attack when calculating vesting).
+    require(tokenGrantsCount(_to) < MAX_GRANTS_PER_ADDRESS);   // To prevent a user being spammed and have his balance locked (out of gas attack when calculating vesting).
 
 
     uint256 count = grants[_to].push(
     uint256 count = grants[_to].push(
                 TokenGrant(
                 TokenGrant(
@@ -75,13 +74,8 @@ contract VestedToken is StandardToken, LimitedTransferToken {
   function revokeTokenGrant(address _holder, uint256 _grantId) public {
   function revokeTokenGrant(address _holder, uint256 _grantId) public {
     TokenGrant grant = grants[_holder][_grantId];
     TokenGrant grant = grants[_holder][_grantId];
 
 
-    if (!grant.revokable) { // Check if grant was revokable
-      throw;
-    }
-
-    if (grant.granter != msg.sender) { // Only granter can revoke it
-      throw;
-    }
+    require(grant.revokable);
+    require(grant.granter == msg.sender); // Only granter can revoke it
 
 
     address receiver = grant.burnsOnRevoke ? 0xdead : msg.sender;
     address receiver = grant.burnsOnRevoke ? 0xdead : msg.sender;
 
 
@@ -108,7 +102,7 @@ contract VestedToken is StandardToken, LimitedTransferToken {
   function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
   function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
     uint256 grantIndex = tokenGrantsCount(holder);
     uint256 grantIndex = tokenGrantsCount(holder);
 
 
-    if (grantIndex == 0) return balanceOf(holder); // shortcut for holder without grants
+    if (grantIndex == 0) return super.transferableTokens(holder, time); // shortcut for holder without grants
 
 
     // Iterate through all the grants the holder has, and add all non-vested tokens
     // Iterate through all the grants the holder has, and add all non-vested tokens
     uint256 nonVested = 0;
     uint256 nonVested = 0;
@@ -121,7 +115,7 @@ contract VestedToken is StandardToken, LimitedTransferToken {
 
 
     // Return the minimum of how many vested can transfer and other value
     // Return the minimum of how many vested can transfer and other value
     // in case there are other limiting transferability factors (default is balanceOf)
     // in case there are other limiting transferability factors (default is balanceOf)
-    return SafeMath.min256(vestedTransferable, super.transferableTokens(holder, time));
+    return Math.min256(vestedTransferable, super.transferableTokens(holder, time));
   }
   }
 
 
   /**
   /**
@@ -225,7 +219,7 @@ contract VestedToken is StandardToken, LimitedTransferToken {
    * @dev Calculate the amount of non vested tokens at a specific time.
    * @dev Calculate the amount of non vested tokens at a specific time.
    * @param grant TokenGrant The grant to be checked.
    * @param grant TokenGrant The grant to be checked.
    * @param time uint64 The time to be checked
    * @param time uint64 The time to be checked
-   * @return An uint256 representing the amount of non vested tokens of a specifc grant on the 
+   * @return An uint256 representing the amount of non vested tokens of a specifc grant on the
    * passed time frame.
    * passed time frame.
    */
    */
   function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
   function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
@@ -241,7 +235,7 @@ contract VestedToken is StandardToken, LimitedTransferToken {
     date = uint64(now);
     date = uint64(now);
     uint256 grantIndex = grants[holder].length;
     uint256 grantIndex = grants[holder].length;
     for (uint256 i = 0; i < grantIndex; i++) {
     for (uint256 i = 0; i < grantIndex; i++) {
-      date = SafeMath.max64(grants[holder][i].vesting, date);
+      date = Math.max64(grants[holder][i].vesting, date);
     }
     }
   }
   }
 }
 }

+ 0 - 14
docs/source/crowdsaletoken.rst

@@ -1,14 +0,0 @@
-CrowdsaleToken
-=============================================
-
-Simple ERC20 Token example, with crowdsale token creation.
-
-Inherits from contract StandardToken.
-
-createTokens(address recipient) payable
-"""""""""""""""""""""""""""""""""""""""""
-Creates tokens based on message value and credits to the recipient.
-
-getPrice() constant returns (uint result)
-"""""""""""""""""""""""""""""""""""""""""
-Returns the amount of tokens per 1 ether.

+ 9 - 0
docs/source/ecrecovery.rst

@@ -0,0 +1,9 @@
+ECReovery
+=============================================
+
+Returns the signer of the the hash using the signature divided in v, r, and s values.
+
+recover(bytes32 hash, bytes sig) internal returns (address)
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+Returns the signer of the the hash using the signature that provides the web3.eth.sign() method.

+ 1 - 1
docs/source/getting-started.rst

@@ -13,7 +13,7 @@ To install the Zeppelin library, run::
 
 
 After that, you'll get all the library's contracts in the contracts/zeppelin folder. You can use the contracts in the library like so::
 After that, you'll get all the library's contracts in the contracts/zeppelin folder. You can use the contracts in the library like so::
 
 
-	import "./zeppelin/Ownable.sol";
+	import "zeppelin-solidity/contracts/Ownable.sol";
 
 
 	contract MyContract is Ownable {
 	contract MyContract is Ownable {
 	  ...
 	  ...

+ 24 - 0
docs/source/math.rst

@@ -0,0 +1,24 @@
+Math
+=============================================
+
+Provides assorted low-level math operations.
+
+max64(uint64 a, uint64 b) internal constant returns (uint64)
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+Returns the largest of two uint64 numbers.
+
+min64(uint64 a, uint64 b) internal constant returns (uint64)
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+Returns the smallest of two uint64 numbers.
+
+max64(uint256 a, uint256 b) internal constant returns (uint256)
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+Returns the largest of two uint256 numbers.
+
+min64(uint256 a, uint256 b) internal constant returns (uint256)
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+Returns the smallest of two uint256 numbers.

+ 2 - 2
docs/source/ownable.rst

@@ -11,6 +11,6 @@ modifier onlyOwner( )
 """"""""""""""""""""""""""""""""""""""
 """"""""""""""""""""""""""""""""""""""
 Prevents function from running if it is called by anyone other than the owner.
 Prevents function from running if it is called by anyone other than the owner.
 
 
-transfer(address newOwner) onlyOwner
+transferOwnership(address newOwner) onlyOwner
 """"""""""""""""""""""""""""""""""""""
 """"""""""""""""""""""""""""""""""""""
-Transfers ownership of the contract to the passed address.
+Transfers ownership of the contract to the passed address.

+ 4 - 4
docs/source/safemath.rst

@@ -8,17 +8,17 @@ assert(bool assertion) internal
 
 
 Throws an error if the passed result is false. Used in this contract by checking mathematical expressions.
 Throws an error if the passed result is false. Used in this contract by checking mathematical expressions.
 
 
-safeMul(uint a, uint b) internal returns (uint)
+mul(uint256 a, uint256 b) internal returns (uint256)
 """""""""""""""""""""""""""""""""""""""""""""""""
 """""""""""""""""""""""""""""""""""""""""""""""""
 
 
 Multiplies two unisgned integers. Asserts that dividing the product by the non-zero multiplicand results in the multiplier.
 Multiplies two unisgned integers. Asserts that dividing the product by the non-zero multiplicand results in the multiplier.
 
 
-safeSub(uint a, uint b) internal returns (uint)
+sub(uint256 a, uint256 b) internal returns (uint256)
 """""""""""""""""""""""""""""""""""""""""""""""""
 """""""""""""""""""""""""""""""""""""""""""""""""
 
 
 Checks that b is not greater than a before subtracting.
 Checks that b is not greater than a before subtracting.
 
 
-safeAdd(uint a, uint b) internal returns (uint)
+add(uint256 a, uint256 b) internal returns (uint256)
 """""""""""""""""""""""""""""""""""""""""""""""""
 """""""""""""""""""""""""""""""""""""""""""""""""
 
 
-Checks that the result is greater than both a and b.
+Checks that the result is greater than both a and b.

+ 1 - 1
ethpm.json

@@ -1,6 +1,6 @@
 {
 {
   "package_name": "zeppelin",
   "package_name": "zeppelin",
-  "version": "1.0.7",
+  "version": "1.2.0",
   "description": "Secure Smart Contract library for Solidity",
   "description": "Secure Smart Contract library for Solidity",
   "authors": [
   "authors": [
     "Manuel Araoz <manuelaraoz@gmail.com>"
     "Manuel Araoz <manuelaraoz@gmail.com>"

+ 6 - 2
package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "zeppelin-solidity",
   "name": "zeppelin-solidity",
-  "version": "1.0.7",
+  "version": "1.2.0",
   "description": "Secure Smart Contract library for Solidity",
   "description": "Secure Smart Contract library for Solidity",
   "main": "truffle.js",
   "main": "truffle.js",
   "scripts": {
   "scripts": {
@@ -35,10 +35,14 @@
     "babel-preset-stage-2": "^6.18.0",
     "babel-preset-stage-2": "^6.18.0",
     "babel-preset-stage-3": "^6.17.0",
     "babel-preset-stage-3": "^6.17.0",
     "babel-register": "^6.23.0",
     "babel-register": "^6.23.0",
+    "chai": "^4.0.2",
+    "chai-as-promised": "^7.0.0",
+    "chai-bignumber": "^2.0.0",
     "coveralls": "^2.13.1",
     "coveralls": "^2.13.1",
     "ethereumjs-testrpc": "^3.0.2",
     "ethereumjs-testrpc": "^3.0.2",
     "mocha-lcov-reporter": "^1.3.0",
     "mocha-lcov-reporter": "^1.3.0",
-    "solidity-coverage": "^0.1.0",
+    "moment": "^2.18.1",
+    "solidity-coverage": "^0.1.7",
     "truffle": "3.2.2"
     "truffle": "3.2.2"
   }
   }
 }
 }

+ 23 - 1
scripts/coverage.sh

@@ -1,3 +1,25 @@
 #! /bin/bash
 #! /bin/bash
 
 
-SOLIDITY_COVERAGE=true ./node_modules/.bin/solidity-coverage
+ 
+
+output=$(nc -z localhost 8555; echo $?)
+[ $output -eq "0" ] && trpc_running=true
+if [ ! $trpc_running ]; then
+  echo "Starting testrpc-sc to generate coverage"
+  # we give each account 1M ether, needed for high-value tests
+  ./node_modules/ethereumjs-testrpc-sc/bin/testrpc --gasLimit 0xfffffffffff --port 8555 \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501203,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501204,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501205,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501206,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501207,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501208,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,1000000000000000000000000"  \
+  > /dev/null &
+  trpc_pid=$!
+fi
+SOLIDITY_COVERAGE=true && ./node_modules/.bin/solidity-coverage
+

+ 14 - 2
scripts/test.sh

@@ -4,10 +4,22 @@ output=$(nc -z localhost 8545; echo $?)
 [ $output -eq "0" ] && trpc_running=true
 [ $output -eq "0" ] && trpc_running=true
 if [ ! $trpc_running ]; then
 if [ ! $trpc_running ]; then
   echo "Starting our own testrpc node instance"
   echo "Starting our own testrpc node instance"
-  testrpc > /dev/null &
+  # we give each account 1M ether, needed for high-value tests
+  testrpc \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501200,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501201,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501202,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501203,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501204,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501205,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501206,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501207,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501208,1000000000000000000000000"  \
+    --account="0x2bdd21761a483f71054e14f5b827213567971c676928d9a1808cbfa4b7501209,1000000000000000000000000"  \
+  > /dev/null &
   trpc_pid=$!
   trpc_pid=$!
 fi
 fi
-./node_modules/truffle/cli.js test
+./node_modules/truffle/cli.js test "$@"
 if [ ! $trpc_running ]; then
 if [ ! $trpc_running ]; then
   kill -9 $trpc_pid
   kill -9 $trpc_pid
 fi
 fi

+ 90 - 0
test/CappedCrowdsale.js

@@ -0,0 +1,90 @@
+import ether from './helpers/ether'
+import advanceToBlock from './helpers/advanceToBlock'
+import EVMThrow from './helpers/EVMThrow'
+
+const BigNumber = web3.BigNumber
+
+require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+const CappedCrowdsale = artifacts.require('./helpers/CappedCrowdsaleImpl.sol')
+const MintableToken = artifacts.require('MintableToken')
+
+contract('CappedCrowdsale', function ([_, wallet]) {
+
+  const rate = new BigNumber(1000)
+
+  const cap = ether(300)
+  const lessThanCap = ether(60)
+
+  describe('creating a valid crowdsale', function () {
+
+    it('should fail with zero cap', async function () {
+      await CappedCrowdsale.new(this.startBlock, this.endBlock, rate, wallet, 0).should.be.rejectedWith(EVMThrow);
+    })
+
+  });
+
+
+  beforeEach(async function () {
+    this.startBlock = web3.eth.blockNumber + 10
+    this.endBlock =   web3.eth.blockNumber + 20
+
+    this.crowdsale = await CappedCrowdsale.new(this.startBlock, this.endBlock, rate, wallet, cap)
+
+    this.token = MintableToken.at(await this.crowdsale.token())
+  })
+
+  describe('accepting payments', function () {
+
+    beforeEach(async function () {
+      await advanceToBlock(this.startBlock - 1)
+    })
+
+    it('should accept payments within cap', async function () {
+      await this.crowdsale.send(cap.minus(lessThanCap)).should.be.fulfilled
+      await this.crowdsale.send(lessThanCap).should.be.fulfilled
+    })
+
+    it('should reject payments outside cap', async function () {
+      await this.crowdsale.send(cap)
+      await this.crowdsale.send(1).should.be.rejectedWith(EVMThrow)
+    })
+
+    it('should reject payments that exceed cap', async function () {
+      await this.crowdsale.send(cap.plus(1)).should.be.rejectedWith(EVMThrow)
+    })
+
+  })
+
+  describe('ending', function () {
+
+    beforeEach(async function () {
+      await advanceToBlock(this.startBlock - 1)
+    })
+
+    it('should not be ended if under cap', async function () {
+      let hasEnded = await this.crowdsale.hasEnded()
+      hasEnded.should.equal(false)
+      await this.crowdsale.send(lessThanCap)
+      hasEnded = await this.crowdsale.hasEnded()
+      hasEnded.should.equal(false)
+    })
+
+    it('should not be ended if just under cap', async function () {
+      await this.crowdsale.send(cap.minus(1))
+      let hasEnded = await this.crowdsale.hasEnded()
+      hasEnded.should.equal(false)
+    })
+
+    it('should be ended if cap reached', async function () {
+      await this.crowdsale.send(cap)
+      let hasEnded = await this.crowdsale.hasEnded()
+      hasEnded.should.equal(true)
+    })
+
+  })
+
+})

+ 143 - 0
test/Crowdsale.js

@@ -0,0 +1,143 @@
+import ether from './helpers/ether'
+import advanceToBlock from './helpers/advanceToBlock'
+import EVMThrow from './helpers/EVMThrow'
+
+const BigNumber = web3.BigNumber
+
+const should = require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+const Crowdsale = artifacts.require('Crowdsale')
+const MintableToken = artifacts.require('MintableToken')
+
+contract('Crowdsale', function ([_, investor, wallet, purchaser]) {
+
+  const rate = new BigNumber(1000)
+  const value = ether(42)
+
+  const expectedTokenAmount = rate.mul(value)
+
+  beforeEach(async function () {
+    this.startBlock = web3.eth.blockNumber + 10
+    this.endBlock =   web3.eth.blockNumber + 20
+
+    this.crowdsale = await Crowdsale.new(this.startBlock, this.endBlock, rate, wallet)
+
+    this.token = MintableToken.at(await this.crowdsale.token())
+  })
+
+  it('should be token owner', async function () {
+    const owner = await this.token.owner()
+    owner.should.equal(this.crowdsale.address)
+  })
+
+  it('should be ended only after end', async function () {
+    let ended = await this.crowdsale.hasEnded()
+    ended.should.equal(false)
+    await advanceToBlock(this.endBlock + 1)
+    ended = await this.crowdsale.hasEnded()
+    ended.should.equal(true)
+  })
+
+  describe('accepting payments', function () {
+
+    it('should reject payments before start', async function () {
+      await this.crowdsale.send(value).should.be.rejectedWith(EVMThrow)
+      await this.crowdsale.buyTokens(investor, value, {from: purchaser}).should.be.rejectedWith(EVMThrow)
+    })
+
+    it('should accept payments after start', async function () {
+      await advanceToBlock(this.startBlock - 1)
+      await this.crowdsale.send(value).should.be.fulfilled
+      await this.crowdsale.buyTokens(investor, {value: value, from: purchaser}).should.be.fulfilled
+    })
+
+    it('should reject payments after end', async function () {
+      await advanceToBlock(this.endBlock)
+      await this.crowdsale.send(value).should.be.rejectedWith(EVMThrow)
+      await this.crowdsale.buyTokens(investor, {value: value, from: purchaser}).should.be.rejectedWith(EVMThrow)
+    })
+
+  })
+
+  describe('high-level purchase', function () {
+
+    beforeEach(async function() {
+      await advanceToBlock(this.startBlock)
+    })
+
+    it('should log purchase', async function () {
+      const {logs} = await this.crowdsale.sendTransaction({value: value, from: investor})
+
+      const event = logs.find(e => e.event === 'TokenPurchase')
+
+      should.exist(event)
+      event.args.purchaser.should.equal(investor)
+      event.args.beneficiary.should.equal(investor)
+      event.args.value.should.be.bignumber.equal(value)
+      event.args.amount.should.be.bignumber.equal(expectedTokenAmount)
+    })
+
+    it('should increase totalSupply', async function () {
+      await this.crowdsale.send(value)
+      const totalSupply = await this.token.totalSupply()
+      totalSupply.should.be.bignumber.equal(expectedTokenAmount)
+    })
+
+    it('should assign tokens to sender', async function () {
+      await this.crowdsale.sendTransaction({value: value, from: investor})
+      let balance = await this.token.balanceOf(investor);
+      balance.should.be.bignumber.equal(expectedTokenAmount)
+    })
+
+    it('should forward funds to wallet', async function () {
+      const pre = web3.eth.getBalance(wallet)
+      await this.crowdsale.sendTransaction({value, from: investor})
+      const post = web3.eth.getBalance(wallet)
+      post.minus(pre).should.be.bignumber.equal(value)
+    })
+
+  })
+
+  describe('low-level purchase', function () {
+
+    beforeEach(async function() {
+      await advanceToBlock(this.startBlock)
+    })
+
+    it('should log purchase', async function () {
+      const {logs} = await this.crowdsale.buyTokens(investor, {value: value, from: purchaser})
+
+      const event = logs.find(e => e.event === 'TokenPurchase')
+
+      should.exist(event)
+      event.args.purchaser.should.equal(purchaser)
+      event.args.beneficiary.should.equal(investor)
+      event.args.value.should.be.bignumber.equal(value)
+      event.args.amount.should.be.bignumber.equal(expectedTokenAmount)
+    })
+
+    it('should increase totalSupply', async function () {
+      await this.crowdsale.buyTokens(investor, {value, from: purchaser})
+      const totalSupply = await this.token.totalSupply()
+      totalSupply.should.be.bignumber.equal(expectedTokenAmount)
+    })
+
+    it('should assign tokens to beneficiary', async function () {
+      await this.crowdsale.buyTokens(investor, {value, from: purchaser})
+      const balance = await this.token.balanceOf(investor)
+      balance.should.be.bignumber.equal(expectedTokenAmount)
+    })
+
+    it('should forward funds to wallet', async function () {
+      const pre = web3.eth.getBalance(wallet)
+      await this.crowdsale.buyTokens(investor, {value, from: purchaser})
+      const post = web3.eth.getBalance(wallet)
+      post.minus(pre).should.be.bignumber.equal(value)
+    })
+
+  })
+
+})

+ 26 - 1
test/DayLimit.js

@@ -1,9 +1,11 @@
 'use strict';
 'use strict';
 const assertJump = require('./helpers/assertJump');
 const assertJump = require('./helpers/assertJump');
+const timer = require('./helpers/timer');
 
 
-var DayLimitMock = artifacts.require('helpers/DayLimitMock.sol');
+var DayLimitMock = artifacts.require('./helpers/DayLimitMock.sol');
 
 
 contract('DayLimit', function(accounts) {
 contract('DayLimit', function(accounts) {
+  const day = 60 * 60 * 24;
 
 
   let dayLimit;
   let dayLimit;
   let initLimit = 10;
   let initLimit = 10;
@@ -77,4 +79,27 @@ contract('DayLimit', function(accounts) {
     assert.equal(spentToday, 3);
     assert.equal(spentToday, 3);
   });
   });
 
 
+  it('should allow spending if daily limit is reached and then the next has come', async function() {
+    let limit = 10;
+    let dayLimit = await DayLimitMock.new(limit);
+
+    await dayLimit.attemptSpend(8);
+    let spentToday = await dayLimit.spentToday();
+    assert.equal(spentToday, 8);
+
+    try {
+      await dayLimit.attemptSpend(3);
+    } catch(error) {
+      assertJump(error);
+    }
+    spentToday = await dayLimit.spentToday();
+    assert.equal(spentToday, 8);
+
+    await timer(day);
+
+    await dayLimit.attemptSpend(3);
+    spentToday = await dayLimit.spentToday();
+    assert.equal(spentToday, 3);
+  });
+
 });
 });

+ 55 - 0
test/ECRecovery.js

@@ -0,0 +1,55 @@
+var ECRecovery = artifacts.require("../contracts/ECRecovery.sol");
+var utils = require('ethereumjs-util');
+var hashMessage = require('./helpers/hashMessage.js');
+
+contract('ECRecovery', function(accounts) {
+
+  let ecrecovery;
+
+  before(async function() {
+    ecrecovery = await ECRecovery.new();
+  });
+
+  it("recover v0", async function() {
+    // Signature generated outside testrpc with method web3.eth.sign(signer, message)
+    let signer = '0x2cc1166f6212628a0deef2b33befb2187d35b86c';
+    let message = '0x7dbaf558b0a1a5dc7a67202117ab143c1d8605a983e4a743bc06fcc03162dc0d'; // web3.sha3('OpenZeppelin')
+    let signature = '0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be89200';
+    assert.equal(signer, await ecrecovery.recover(message, signature));
+  });
+
+  it("recover v1", async function() {
+    // Signature generated outside testrpc with method web3.eth.sign(signer, message)
+    let signer = '0x1e318623ab09fe6de3c9b8672098464aeda9100e';
+    let message = '0x7dbaf558b0a1a5dc7a67202117ab143c1d8605a983e4a743bc06fcc03162dc0d'; // web3.sha3('OpenZeppelin')
+    let signature = '0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e001';
+    assert.equal(signer, await ecrecovery.recover(message, signature));
+  });
+
+  it("recover using web3.eth.sign()", async function() {
+    // Create the signature using account[0]
+    const signature = web3.eth.sign(web3.eth.accounts[0], web3.sha3('OpenZeppelin'));
+
+    // Recover the signer address form the generated message and signature.
+    assert.equal(web3.eth.accounts[0], await ecrecovery.recover(hashMessage('OpenZeppelin'), signature));
+  });
+
+  it("recover using web3.eth.sign() should return wrong signer", async function() {
+    // Create the signature using account[0]
+    const signature = web3.eth.sign(web3.eth.accounts[0], web3.sha3('OpenZeppelin'));
+
+    // Recover the signer address form the generated message and wrong signature.
+    assert.notEqual(web3.eth.accounts[0], await ecrecovery.recover(hashMessage('Test'), signature));
+  });
+
+  it("recover should fail when a wrong hash is sent", async function() {
+    // Create the signature using account[0]
+    let signature = web3.eth.sign(web3.eth.accounts[0], web3.sha3('OpenZeppelin'));
+
+    // Recover the signer address form the generated message and wrong signature.
+    assert.equal('0x0000000000000000000000000000000000000000',
+      await ecrecovery.recover(hashMessage('OpenZeppelin').substring(2), signature)
+    );
+  });
+
+});

+ 61 - 0
test/FinalizableCrowdsale.js

@@ -0,0 +1,61 @@
+import advanceToBlock from './helpers/advanceToBlock'
+import EVMThrow from './helpers/EVMThrow'
+
+const BigNumber = web3.BigNumber
+
+const should = require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+const FinalizableCrowdsale = artifacts.require('./helpers/FinalizableCrowdsaleImpl.sol')
+const MintableToken = artifacts.require('MintableToken')
+
+contract('FinalizableCrowdsale', function ([_, owner, wallet, thirdparty]) {
+
+  const rate = new BigNumber(1000)
+
+  beforeEach(async function () {
+    this.startBlock = web3.eth.blockNumber + 10
+    this.endBlock = web3.eth.blockNumber + 20
+
+    this.crowdsale = await FinalizableCrowdsale.new(this.startBlock, this.endBlock, rate, wallet, {from: owner})
+
+    this.token = MintableToken.at(await this.crowdsale.token())
+  })
+
+  it('cannot be finalized before ending', async function () {
+    await this.crowdsale.finalize({from: owner}).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('cannot be finalized by third party after ending', async function () {
+    await advanceToBlock(this.endBlock)
+    await this.crowdsale.finalize({from: thirdparty}).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('can be finalized by owner after ending', async function () {
+    await advanceToBlock(this.endBlock)
+    await this.crowdsale.finalize({from: owner}).should.be.fulfilled
+  })
+
+  it('cannot be finalized twice', async function () {
+    await advanceToBlock(this.endBlock + 1)
+    await this.crowdsale.finalize({from: owner})
+    await this.crowdsale.finalize({from: owner}).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('logs finalized', async function () {
+    await advanceToBlock(this.endBlock)
+    const {logs} = await this.crowdsale.finalize({from: owner})
+    const event = logs.find(e => e.event === 'Finalized')
+    should.exist(event)
+  })
+
+  it('finishes minting of token', async function () {
+    await advanceToBlock(this.endBlock)
+    await this.crowdsale.finalize({from: owner})
+    const finished = await this.token.mintingFinished()
+    finished.should.equal(true)
+  })
+
+})

+ 1 - 1
test/MultisigWallet.js

@@ -52,7 +52,7 @@ contract('MultisigWallet', function(accounts) {
 
 
     //Balance of account2 should have increased
     //Balance of account2 should have increased
     let newAccountBalance = web3.eth.getBalance(accounts[2]);
     let newAccountBalance = web3.eth.getBalance(accounts[2]);
-    assert.isTrue(newAccountBalance > accountBalance);
+    assert.isTrue(newAccountBalance.greaterThan(accountBalance));
   });
   });
 
 
   it('should prevent execution of transaction if above daily limit', async function() {
   it('should prevent execution of transaction if above daily limit', async function() {

+ 61 - 0
test/RefundVault.js

@@ -0,0 +1,61 @@
+const BigNumber = web3.BigNumber
+
+require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+import ether from './helpers/ether'
+import EVMThrow from './helpers/EVMThrow'
+
+const RefundVault = artifacts.require('RefundVault')
+
+contract('RefundVault', function ([_, owner, wallet, investor]) {
+
+  const value = ether(42)
+
+  beforeEach(async function () {
+    this.vault = await RefundVault.new(wallet, {from: owner})
+  })
+
+  it('should accept contributions', async function () {
+    await this.vault.deposit(investor, {value, from: owner}).should.be.fulfilled
+  })
+
+  it('should not refund contribution during active state', async function () {
+    await this.vault.deposit(investor, {value, from: owner})
+    await this.vault.refund(investor).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('only owner can enter refund mode', async function () {
+    await this.vault.enableRefunds({from: _}).should.be.rejectedWith(EVMThrow)
+    await this.vault.enableRefunds({from: owner}).should.be.fulfilled
+  })
+
+  it('should refund contribution after entering refund mode', async function () {
+    await this.vault.deposit(investor, {value, from: owner})
+    await this.vault.enableRefunds({from: owner})
+
+    const pre = web3.eth.getBalance(investor)
+    await this.vault.refund(investor)
+    const post = web3.eth.getBalance(investor)
+
+    post.minus(pre).should.be.bignumber.equal(value)
+  })
+
+  it('only owner can close', async function () {
+    await this.vault.close({from: _}).should.be.rejectedWith(EVMThrow)
+    await this.vault.close({from: owner}).should.be.fulfilled
+  })
+
+  it('should forward funds to wallet after closing', async function () {
+    await this.vault.deposit(investor, {value, from: owner})
+
+    const pre = web3.eth.getBalance(wallet)
+    await this.vault.close({from: owner})
+    const post = web3.eth.getBalance(wallet)
+
+    post.minus(pre).should.be.bignumber.equal(value)
+  })
+
+})

+ 76 - 0
test/RefundableCrowdsale.js

@@ -0,0 +1,76 @@
+import ether from './helpers/ether'
+import advanceToBlock from './helpers/advanceToBlock'
+import EVMThrow from './helpers/EVMThrow'
+
+const BigNumber = web3.BigNumber
+
+require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+const RefundableCrowdsale = artifacts.require('./helpers/RefundableCrowdsaleImpl.sol')
+
+contract('RefundableCrowdsale', function ([_, owner, wallet, investor]) {
+
+  const rate = new BigNumber(1000)
+  const goal = ether(800)
+  const lessThanGoal = ether(750)
+
+  describe('creating a valid crowdsale', function () {
+
+    it('should fail with zero goal', async function () {
+      await RefundableCrowdsale.new(this.startBlock, this.endBlock, rate, wallet, 0, {from: owner}).should.be.rejectedWith(EVMThrow);
+    })
+
+  });
+
+
+  beforeEach(async function () {
+    this.startBlock = web3.eth.blockNumber + 10
+    this.endBlock =   web3.eth.blockNumber + 20
+
+    this.crowdsale = await RefundableCrowdsale.new(this.startBlock, this.endBlock, rate, wallet, goal, {from: owner})
+  })
+
+  it('should deny refunds before end', async function () {
+    await this.crowdsale.claimRefund({from: investor}).should.be.rejectedWith(EVMThrow)
+    await advanceToBlock(this.endBlock - 1)
+    await this.crowdsale.claimRefund({from: investor}).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('should deny refunds after end if goal was reached', async function () {
+    await advanceToBlock(this.startBlock - 1)
+    await this.crowdsale.sendTransaction({value: goal, from: investor})
+    await advanceToBlock(this.endBlock)
+    await this.crowdsale.claimRefund({from: investor}).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('should allow refunds after end if goal was not reached', async function () {
+    await advanceToBlock(this.startBlock - 1)
+    await this.crowdsale.sendTransaction({value: lessThanGoal, from: investor})
+    await advanceToBlock(this.endBlock)
+
+    await this.crowdsale.finalize({from: owner})
+
+    const pre = web3.eth.getBalance(investor)
+    await this.crowdsale.claimRefund({from: investor, gasPrice: 0})
+			.should.be.fulfilled
+    const post = web3.eth.getBalance(investor)
+
+    post.minus(pre).should.be.bignumber.equal(lessThanGoal)
+  })
+
+  it('should forward funds to wallet after end if goal was reached', async function () {
+    await advanceToBlock(this.startBlock - 1)
+    await this.crowdsale.sendTransaction({value: goal, from: investor})
+    await advanceToBlock(this.endBlock)
+
+    const pre = web3.eth.getBalance(wallet)
+    await this.crowdsale.finalize({from: owner})
+    const post = web3.eth.getBalance(wallet)
+
+    post.minus(pre).should.be.bignumber.equal(goal)
+  })
+
+})

+ 58 - 0
test/TokenTimelock.js

@@ -0,0 +1,58 @@
+const BigNumber = web3.BigNumber
+
+require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+import moment from 'moment'
+
+import latestTime from './helpers/latestTime'
+import increaseTime from './helpers/increaseTime'
+
+const MintableToken = artifacts.require('MintableToken')
+const TokenTimelock = artifacts.require('TokenTimelock')
+
+contract('TokenTimelock', function ([_, owner, beneficiary]) {
+
+  const amount = new BigNumber(100)
+
+  beforeEach(async function () {
+    this.token = await MintableToken.new({from: owner})
+    this.releaseTime = latestTime().add(1, 'year').unix()
+    this.timelock = await TokenTimelock.new(this.token.address, beneficiary, this.releaseTime)
+    await this.token.mint(this.timelock.address, amount, {from: owner})
+  })
+
+  it('cannot be released before time limit', async function () {
+    await this.timelock.release().should.be.rejected
+  })
+
+  it('cannot be released just before time limit', async function () {
+    await increaseTime(moment.duration(0.99, 'year'))
+    await this.timelock.release().should.be.rejected
+  })
+
+  it('can be released just after limit', async function () {
+    await increaseTime(moment.duration(1.01, 'year'))
+    await this.timelock.release().should.be.fulfilled
+    const balance = await this.token.balanceOf(beneficiary)
+    balance.should.be.bignumber.equal(amount)
+  })
+
+  it('can be released after time limit', async function () {
+    await increaseTime(moment.duration(2, 'year'))
+    await this.timelock.release().should.be.fulfilled
+    const balance = await this.token.balanceOf(beneficiary)
+    balance.should.be.bignumber.equal(amount)
+  })
+
+  it('cannot be released twice', async function () {
+    await increaseTime(moment.duration(2, 'year'))
+    await this.timelock.release().should.be.fulfilled
+    await this.timelock.release().should.be.rejected
+    const balance = await this.token.balanceOf(beneficiary)
+    balance.should.be.bignumber.equal(amount)
+  })
+
+})

+ 1 - 1
test/helpers/BasicTokenMock.sol

@@ -7,7 +7,7 @@ import '../../contracts/token/BasicToken.sol';
 // mock class using BasicToken
 // mock class using BasicToken
 contract BasicTokenMock is BasicToken {
 contract BasicTokenMock is BasicToken {
 
 
-  function BasicTokenMock(address initialAccount, uint initialBalance) {
+  function BasicTokenMock(address initialAccount, uint256 initialBalance) {
     balances[initialAccount] = initialBalance;
     balances[initialAccount] = initialBalance;
     totalSupply = initialBalance;
     totalSupply = initialBalance;
   }
   }

+ 21 - 0
test/helpers/CappedCrowdsaleImpl.sol

@@ -0,0 +1,21 @@
+pragma solidity ^0.4.11;
+
+
+import '../../contracts/crowdsale/CappedCrowdsale.sol';
+
+
+contract CappedCrowdsaleImpl is CappedCrowdsale {
+
+  function CappedCrowdsaleImpl (
+    uint256 _startBlock,
+    uint256 _endBlock,
+    uint256 _rate,
+    address _wallet,
+    uint256 _cap
+  )
+    Crowdsale(_startBlock, _endBlock, _rate, _wallet)
+    CappedCrowdsale(_cap) 
+  {
+  }
+
+}

+ 4 - 4
test/helpers/DayLimitMock.sol

@@ -2,17 +2,17 @@ pragma solidity ^0.4.11;
 import "../../contracts/DayLimit.sol";
 import "../../contracts/DayLimit.sol";
 
 
 contract DayLimitMock is DayLimit {
 contract DayLimitMock is DayLimit {
-  uint public totalSpending;
+  uint256 public totalSpending;
 
 
-  function DayLimitMock(uint _value) DayLimit(_value) {
+  function DayLimitMock(uint256 _value) DayLimit(_value) {
     totalSpending = 0;
     totalSpending = 0;
   }
   }
 
 
-  function attemptSpend(uint _value) external limitedDaily(_value) {
+  function attemptSpend(uint256 _value) external limitedDaily(_value) {
     totalSpending += _value;
     totalSpending += _value;
   }
   }
 
 
-  function setDailyLimit(uint _newLimit) external {
+  function setDailyLimit(uint256 _newLimit) external {
     _setDailyLimit(_newLimit);
     _setDailyLimit(_newLimit);
   }
   }
 
 

+ 3 - 3
test/helpers/ERC23TokenMock.sol

@@ -5,18 +5,18 @@ import '../../contracts/token/BasicToken.sol';
 
 
 
 
 contract ERC23ContractInterface {
 contract ERC23ContractInterface {
-  function tokenFallback(address _from, uint _value, bytes _data) external;
+  function tokenFallback(address _from, uint256 _value, bytes _data) external;
 }
 }
 
 
 contract ERC23TokenMock is BasicToken {
 contract ERC23TokenMock is BasicToken {
 
 
-  function ERC23TokenMock(address initialAccount, uint initialBalance) {
+  function ERC23TokenMock(address initialAccount, uint256 initialBalance) {
     balances[initialAccount] = initialBalance;
     balances[initialAccount] = initialBalance;
     totalSupply = initialBalance;
     totalSupply = initialBalance;
   }
   }
 
 
   // ERC23 compatible transfer function (except the name)
   // ERC23 compatible transfer function (except the name)
-  function transferERC23(address _to, uint _value, bytes _data)
+  function transferERC23(address _to, uint256 _value, bytes _data)
     returns (bool success)
     returns (bool success)
   {
   {
     transfer(_to, _value);
     transfer(_to, _value);

+ 1 - 0
test/helpers/EVMThrow.js

@@ -0,0 +1 @@
+export default 'invalid opcode'

+ 20 - 0
test/helpers/FinalizableCrowdsaleImpl.sol

@@ -0,0 +1,20 @@
+pragma solidity ^0.4.11;
+
+
+import '../../contracts/crowdsale/FinalizableCrowdsale.sol';
+
+
+contract FinalizableCrowdsaleImpl is FinalizableCrowdsale {
+
+  function FinalizableCrowdsaleImpl (
+    uint256 _startBlock,
+    uint256 _endBlock,
+    uint256 _rate,
+    address _wallet
+  )
+    Crowdsale(_startBlock, _endBlock, _rate, _wallet)
+    FinalizableCrowdsale() 
+  {
+  }
+
+}

+ 2 - 2
test/helpers/MultisigWalletMock.sol

@@ -2,9 +2,9 @@ pragma solidity ^0.4.11;
 import "../../contracts/MultisigWallet.sol";
 import "../../contracts/MultisigWallet.sol";
 
 
 contract MultisigWalletMock is MultisigWallet {
 contract MultisigWalletMock is MultisigWallet {
-  uint public totalSpending;
+  uint256 public totalSpending;
 
 
-  function MultisigWalletMock(address[] _owners, uint _required, uint _daylimit)
+  function MultisigWalletMock(address[] _owners, uint256 _required, uint256 _daylimit)
     MultisigWallet(_owners, _required, _daylimit) payable { }
     MultisigWallet(_owners, _required, _daylimit) payable { }
 
 
   function changeOwner(address _from, address _to) external { }
   function changeOwner(address _from, address _to) external { }

+ 1 - 1
test/helpers/PausableMock.sol

@@ -7,7 +7,7 @@ import '../../contracts/lifecycle/Pausable.sol';
 // mock class using Pausable
 // mock class using Pausable
 contract PausableMock is Pausable {
 contract PausableMock is Pausable {
   bool public drasticMeasureTaken;
   bool public drasticMeasureTaken;
-  uint public count;
+  uint256 public count;
 
 
   function PausableMock() {
   function PausableMock() {
     drasticMeasureTaken = false;
     drasticMeasureTaken = false;

+ 1 - 1
test/helpers/PullPaymentMock.sol

@@ -10,7 +10,7 @@ contract PullPaymentMock is PullPayment {
   function PullPaymentMock() payable { }
   function PullPaymentMock() payable { }
 
 
   // test helper function to call asyncSend
   // test helper function to call asyncSend
-  function callSend(address dest, uint amount) {
+  function callSend(address dest, uint256 amount) {
     asyncSend(dest, amount);
     asyncSend(dest, amount);
   }
   }
 
 

+ 1 - 1
test/helpers/ReentrancyMock.sol

@@ -15,7 +15,7 @@ contract ReentrancyMock is ReentrancyGuard {
     counter += 1;
     counter += 1;
   }
   }
 
 
-  function countLocalRecursive(uint n) public nonReentrant {
+  function countLocalRecursive(uint256 n) public nonReentrant {
     if(n > 0) {
     if(n > 0) {
       count();
       count();
       countLocalRecursive(n - 1);
       countLocalRecursive(n - 1);

+ 21 - 0
test/helpers/RefundableCrowdsaleImpl.sol

@@ -0,0 +1,21 @@
+pragma solidity ^0.4.11;
+
+
+import '../../contracts/crowdsale/RefundableCrowdsale.sol';
+
+
+contract RefundableCrowdsaleImpl is RefundableCrowdsale {
+
+  function RefundableCrowdsaleImpl (
+    uint256 _startBlock,
+    uint256 _endBlock,
+    uint256 _rate,
+    address _wallet,
+    uint256 _goal
+  )
+    Crowdsale(_startBlock, _endBlock, _rate, _wallet)
+    RefundableCrowdsale(_goal) 
+  {
+  }
+
+}

+ 5 - 5
test/helpers/SafeMathMock.sol

@@ -1,21 +1,21 @@
 pragma solidity ^0.4.11;
 pragma solidity ^0.4.11;
 
 
 
 
-import '../../contracts/SafeMath.sol';
+import '../../contracts/math/SafeMath.sol';
 
 
 
 
 contract SafeMathMock {
 contract SafeMathMock {
-  uint public result;
+  uint256 public result;
 
 
-  function multiply(uint a, uint b) {
+  function multiply(uint256 a, uint256 b) {
     result = SafeMath.mul(a, b);
     result = SafeMath.mul(a, b);
   }
   }
 
 
-  function subtract(uint a, uint b) {
+  function subtract(uint256 a, uint256 b) {
     result = SafeMath.sub(a, b);
     result = SafeMath.sub(a, b);
   }
   }
 
 
-  function add(uint a, uint b) {
+  function add(uint256 a, uint256 b) {
     result = SafeMath.add(a, b);
     result = SafeMath.add(a, b);
   }
   }
 }
 }

+ 2 - 2
test/helpers/ShareableMock.sol

@@ -3,9 +3,9 @@ import "../../contracts/ownership/Shareable.sol";
 
 
 contract ShareableMock is Shareable {
 contract ShareableMock is Shareable {
 
 
-  uint public count = 0;
+  uint256 public count = 0;
 
 
-  function ShareableMock(address[] _owners, uint _required) Shareable(_owners, _required) {
+  function ShareableMock(address[] _owners, uint256 _required) Shareable(_owners, _required) {
 
 
   }
   }
 
 

+ 1 - 1
test/helpers/StandardTokenMock.sol

@@ -7,7 +7,7 @@ import '../../contracts/token/StandardToken.sol';
 // mock class using StandardToken
 // mock class using StandardToken
 contract StandardTokenMock is StandardToken {
 contract StandardTokenMock is StandardToken {
 
 
-  function StandardTokenMock(address initialAccount, uint initialBalance) {
+  function StandardTokenMock(address initialAccount, uint256 initialBalance) {
     balances[initialAccount] = initialBalance;
     balances[initialAccount] = initialBalance;
     totalSupply = initialBalance;
     totalSupply = initialBalance;
   }
   }

+ 1 - 1
test/helpers/VestedTokenMock.sol

@@ -4,7 +4,7 @@ import '../../contracts/token/VestedToken.sol';
 
 
 // mock class using StandardToken
 // mock class using StandardToken
 contract VestedTokenMock is VestedToken {
 contract VestedTokenMock is VestedToken {
-  function VestedTokenMock(address initialAccount, uint initialBalance) {
+  function VestedTokenMock(address initialAccount, uint256 initialBalance) {
     balances[initialAccount] = initialBalance;
     balances[initialAccount] = initialBalance;
     totalSupply = initialBalance;
     totalSupply = initialBalance;
   }
   }

+ 22 - 0
test/helpers/advanceToBlock.js

@@ -0,0 +1,22 @@
+export function advanceBlock() {
+  return new Promise((resolve, reject) => {
+    web3.currentProvider.sendAsync({
+      jsonrpc: '2.0',
+      method: 'evm_mine',
+      id: Date.now(),
+    }, (err, res) => {
+      return err ? reject(err) : resolve(res)
+    })
+  })
+}
+
+// Advances the block number so that the last mined block is `number`.
+export default async function advanceToBlock(number) {
+  if (web3.eth.blockNumber > number) {
+    throw Error(`block number ${number} is in the past (current is ${web3.eth.blockNumber})`)
+  }
+
+  while (web3.eth.blockNumber < number) {
+    await advanceBlock()
+  }
+}

+ 3 - 0
test/helpers/ether.js

@@ -0,0 +1,3 @@
+export default function ether(n) {
+  return new web3.BigNumber(web3.toWei(n, 'ether'))
+}

+ 8 - 0
test/helpers/hashMessage.js

@@ -0,0 +1,8 @@
+import utils from 'ethereumjs-util';
+
+// Hash and add same prefix to the hash that testrpc use.
+module.exports = function(message) {
+  const messageHex = new Buffer(utils.sha3(message).toString('hex'), 'hex');
+  const prefix = utils.toBuffer('\u0019Ethereum Signed Message:\n' + messageHex.length.toString());
+  return utils.bufferToHex( utils.sha3(Buffer.concat([prefix, messageHex])) );
+};

+ 23 - 0
test/helpers/increaseTime.js

@@ -0,0 +1,23 @@
+// Increases testrpc time by the passed duration (a moment.js instance)
+export default function increaseTime(duration) {
+  const id = Date.now()
+
+  return new Promise((resolve, reject) => {
+    web3.currentProvider.sendAsync({
+      jsonrpc: '2.0',
+      method: 'evm_increaseTime',
+      params: [duration.asSeconds()],
+      id: id,
+    }, err1 => {
+      if (err1) return reject(err1)
+
+      web3.currentProvider.sendAsync({
+        jsonrpc: '2.0',
+        method: 'evm_mine',
+        id: id+1,
+      }, (err2, res) => {
+        return err2 ? reject(err2) : resolve(res)
+      })
+    })
+  })
+}

+ 6 - 0
test/helpers/latestTime.js

@@ -0,0 +1,6 @@
+import moment from 'moment'
+
+// Returns a moment.js instance representing the time of the last mined block
+export default function latestTime() {
+  return moment.unix(web3.eth.getBlock('latest').timestamp)
+}

+ 449 - 44
yarn.lock

@@ -46,10 +46,24 @@ accepts@1.3.3:
     mime-types "~2.1.11"
     mime-types "~2.1.11"
     negotiator "0.6.1"
     negotiator "0.6.1"
 
 
+acorn-jsx@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+  dependencies:
+    acorn "^3.0.4"
+
 acorn@^1.0.3:
 acorn@^1.0.3:
   version "1.2.2"
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014"
 
 
+acorn@^3.0.4:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
+acorn@^5.0.1:
+  version "5.0.3"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
+
 adm-zip@~0.4.3:
 adm-zip@~0.4.3:
   version "0.4.7"
   version "0.4.7"
   resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1"
   resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1"
@@ -62,7 +76,11 @@ after@0.8.2:
   version "0.8.2"
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
   resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
 
 
-ajv@^4.9.1:
+ajv-keywords@^1.0.0:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
+
+ajv@^4.7.0, ajv@^4.9.1:
   version "4.11.8"
   version "4.11.8"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
   dependencies:
   dependencies:
@@ -94,10 +112,18 @@ ansi-align@^1.1.0:
   dependencies:
   dependencies:
     string-width "^1.0.1"
     string-width "^1.0.1"
 
 
+ansi-escapes@^1.1.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+
 ansi-regex@^2.0.0:
 ansi-regex@^2.0.0:
   version "2.1.1"
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
 
 
+ansi-regex@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+
 ansi-styles@^2.2.1:
 ansi-styles@^2.2.1:
   version "2.2.1"
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -252,7 +278,7 @@ babel-cli@*:
   optionalDependencies:
   optionalDependencies:
     chokidar "^1.6.1"
     chokidar "^1.6.1"
 
 
-babel-code-frame@^6.22.0:
+babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
   version "6.22.0"
   version "6.22.0"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
   dependencies:
   dependencies:
@@ -855,7 +881,11 @@ better-assert@~1.0.0:
   dependencies:
   dependencies:
     callsite "1.0.0"
     callsite "1.0.0"
 
 
-"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", "bignumber.js@git+https://github.com/debris/bignumber.js.git#master":
+"bignumber.js@git+https://github.com/debris/bignumber.js#master":
+  version "2.0.7"
+  resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9"
+
+"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
   version "2.0.7"
   version "2.0.7"
   resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
   resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
 
 
@@ -875,23 +905,23 @@ bindings@^1.2.1, bindings@~1.2.1:
   version "1.2.1"
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
   resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11"
 
 
-bip39@^2.2.0:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.3.1.tgz#c8238abc09d719c6f01136ef042daccc5dc3581b"
+bip39@2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.2.0.tgz#40e73f70674c267f148cdbf8374f2a50be166b0d"
   dependencies:
   dependencies:
     create-hash "^1.1.0"
     create-hash "^1.1.0"
-    pbkdf2 "^3.0.9"
+    pbkdf2 "^3.0.0"
     randombytes "^2.0.1"
     randombytes "^2.0.1"
-    safe-buffer "^5.0.1"
     unorm "^1.3.3"
     unorm "^1.3.3"
 
 
-bip39@~2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.2.0.tgz#40e73f70674c267f148cdbf8374f2a50be166b0d"
+bip39@^2.2.0:
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.3.1.tgz#c8238abc09d719c6f01136ef042daccc5dc3581b"
   dependencies:
   dependencies:
     create-hash "^1.1.0"
     create-hash "^1.1.0"
-    pbkdf2 "^3.0.0"
+    pbkdf2 "^3.0.9"
     randombytes "^2.0.1"
     randombytes "^2.0.1"
+    safe-buffer "^5.0.1"
     unorm "^1.3.3"
     unorm "^1.3.3"
 
 
 bip66@^1.1.3:
 bip66@^1.1.3:
@@ -1102,10 +1132,20 @@ call@3.x.x:
     boom "4.x.x"
     boom "4.x.x"
     hoek "4.x.x"
     hoek "4.x.x"
 
 
+caller-path@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
+  dependencies:
+    callsites "^0.2.0"
+
 callsite@1.0.0:
 callsite@1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
   resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
 
 
+callsites@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
+
 camelcase@^1.0.2, camelcase@^1.2.1:
 camelcase@^1.0.2, camelcase@^1.2.1:
   version "1.2.1"
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
@@ -1151,6 +1191,17 @@ center-align@^0.1.1:
     align-text "^0.1.3"
     align-text "^0.1.3"
     lazy-cache "^1.0.3"
     lazy-cache "^1.0.3"
 
 
+chai-as-promised@^7.0.0:
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.0.tgz#5bc1be34e39e8555785945dd1085222f720577e7"
+  dependencies:
+    check-error "^1.0.2"
+    eslint "^3.19.0"
+
+chai-bignumber@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/chai-bignumber/-/chai-bignumber-2.0.0.tgz#0cbf9b81790801c3f24fb77f59fa1e17a9c6e3f2"
+
 chai@^3.3.0, chai@^3.5.0:
 chai@^3.3.0, chai@^3.5.0:
   version "3.5.0"
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
   resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
@@ -1159,7 +1210,18 @@ chai@^3.3.0, chai@^3.5.0:
     deep-eql "^0.1.3"
     deep-eql "^0.1.3"
     type-detect "^1.0.0"
     type-detect "^1.0.0"
 
 
-chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1:
+chai@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.0.2.tgz#2f7327c4de6f385dd7787999e2ab02697a32b83b"
+  dependencies:
+    assertion-error "^1.0.1"
+    check-error "^1.0.1"
+    deep-eql "^2.0.1"
+    get-func-name "^2.0.0"
+    pathval "^1.0.0"
+    type-detect "^4.0.0"
+
+chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
   version "1.1.3"
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   dependencies:
   dependencies:
@@ -1169,6 +1231,10 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1:
     strip-ansi "^3.0.0"
     strip-ansi "^3.0.0"
     supports-color "^2.0.0"
     supports-color "^2.0.0"
 
 
+check-error@^1.0.1, check-error@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
+
 checkpoint-store@^1.1.0:
 checkpoint-store@^1.1.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06"
   resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06"
@@ -1224,10 +1290,24 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
   dependencies:
   dependencies:
     inherits "^2.0.1"
     inherits "^2.0.1"
 
 
+circular-json@^0.3.1:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
+
 cli-boxes@^1.0.0:
 cli-boxes@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
   resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
 
 
+cli-cursor@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
+  dependencies:
+    restore-cursor "^1.0.1"
+
+cli-width@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
+
 cliui@^2.1.0:
 cliui@^2.1.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
@@ -1419,6 +1499,12 @@ crypto-js@^3.1.9-1:
   version "3.1.9-1"
   version "3.1.9-1"
   resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8"
   resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.9-1.tgz#fda19e761fc077e01ffbfdc6e9fdfc59e8806cd8"
 
 
+d@1:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
+  dependencies:
+    es5-ext "^0.10.9"
+
 dashdash@^1.12.0:
 dashdash@^1.12.0:
   version "1.14.1"
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -1465,6 +1551,12 @@ deep-eql@^0.1.3:
   dependencies:
   dependencies:
     type-detect "0.1.1"
     type-detect "0.1.1"
 
 
+deep-eql@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a"
+  dependencies:
+    type-detect "^3.0.0"
+
 deep-equal@~1.0.1:
 deep-equal@~1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
   resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
@@ -1500,7 +1592,7 @@ defined@~1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
   resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
 
 
-del@^2.2.0:
+del@^2.0.2, del@^2.2.0:
   version "2.2.2"
   version "2.2.2"
   resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
   resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
   dependencies:
   dependencies:
@@ -1561,6 +1653,13 @@ diff@3.2.0:
   version "3.2.0"
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
 
 
+doctrine@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
+  dependencies:
+    esutils "^2.0.2"
+    isarray "^1.0.0"
+
 dom-walk@^0.1.0:
 dom-walk@^0.1.0:
   version "0.1.1"
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
   resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
@@ -1697,6 +1796,58 @@ es-to-primitive@^1.1.1:
     is-date-object "^1.0.1"
     is-date-object "^1.0.1"
     is-symbol "^1.0.1"
     is-symbol "^1.0.1"
 
 
+es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
+  version "0.10.23"
+  resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.23.tgz#7578b51be974207a5487821b56538c224e4e7b38"
+  dependencies:
+    es6-iterator "2"
+    es6-symbol "~3.1"
+
+es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512"
+  dependencies:
+    d "1"
+    es5-ext "^0.10.14"
+    es6-symbol "^3.1"
+
+es6-map@^0.1.3:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+    es6-iterator "~2.0.1"
+    es6-set "~0.1.5"
+    es6-symbol "~3.1.1"
+    event-emitter "~0.3.5"
+
+es6-set@~0.1.5:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+    es6-iterator "~2.0.1"
+    es6-symbol "3.1.1"
+    event-emitter "~0.3.5"
+
+es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
+es6-weak-map@^2.0.1:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f"
+  dependencies:
+    d "1"
+    es5-ext "^0.10.14"
+    es6-iterator "^2.0.1"
+    es6-symbol "^3.1.1"
+
 escape-html@~1.0.3:
 escape-html@~1.0.3:
   version "1.0.3"
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -1705,7 +1856,7 @@ escape-string-regexp@1.0.2:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1"
 
 
-escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
+escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
   version "1.0.5"
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
 
 
@@ -1739,6 +1890,62 @@ escodegen@~1.3.2:
   optionalDependencies:
   optionalDependencies:
     source-map "~0.1.33"
     source-map "~0.1.33"
 
 
+escope@^3.6.0:
+  version "3.6.0"
+  resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3"
+  dependencies:
+    es6-map "^0.1.3"
+    es6-weak-map "^2.0.1"
+    esrecurse "^4.1.0"
+    estraverse "^4.1.1"
+
+eslint@^3.19.0:
+  version "3.19.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
+  dependencies:
+    babel-code-frame "^6.16.0"
+    chalk "^1.1.3"
+    concat-stream "^1.5.2"
+    debug "^2.1.1"
+    doctrine "^2.0.0"
+    escope "^3.6.0"
+    espree "^3.4.0"
+    esquery "^1.0.0"
+    estraverse "^4.2.0"
+    esutils "^2.0.2"
+    file-entry-cache "^2.0.0"
+    glob "^7.0.3"
+    globals "^9.14.0"
+    ignore "^3.2.0"
+    imurmurhash "^0.1.4"
+    inquirer "^0.12.0"
+    is-my-json-valid "^2.10.0"
+    is-resolvable "^1.0.0"
+    js-yaml "^3.5.1"
+    json-stable-stringify "^1.0.0"
+    levn "^0.3.0"
+    lodash "^4.0.0"
+    mkdirp "^0.5.0"
+    natural-compare "^1.4.0"
+    optionator "^0.8.2"
+    path-is-inside "^1.0.1"
+    pluralize "^1.2.1"
+    progress "^1.1.8"
+    require-uncached "^1.0.2"
+    shelljs "^0.7.5"
+    strip-bom "^3.0.0"
+    strip-json-comments "~2.0.1"
+    table "^3.7.8"
+    text-table "~0.2.0"
+    user-home "^2.0.0"
+
+espree@^3.4.0:
+  version "3.4.3"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374"
+  dependencies:
+    acorn "^5.0.1"
+    acorn-jsx "^3.0.0"
+
 esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1:
 esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1:
   version "2.7.3"
   version "2.7.3"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
@@ -1751,10 +1958,27 @@ esprima@~1.1.1:
   version "1.1.1"
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.1.1.tgz#5b6f1547f4d102e670e140c509be6771d6aeb549"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.1.1.tgz#5b6f1547f4d102e670e140c509be6771d6aeb549"
 
 
+esquery@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+  dependencies:
+    estraverse "^4.0.0"
+
+esrecurse@^4.1.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163"
+  dependencies:
+    estraverse "^4.1.0"
+    object-assign "^4.0.1"
+
 estraverse@^1.9.1:
 estraverse@^1.9.1:
   version "1.9.3"
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
 
 
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+
 estraverse@~1.3.0:
 estraverse@~1.3.0:
   version "1.3.2"
   version "1.3.2"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.3.2.tgz#37c2b893ef13d723f276d878d60d8535152a6c42"
   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.3.2.tgz#37c2b893ef13d723f276d878d60d8535152a6c42"
@@ -1814,13 +2038,13 @@ ethereumjs-block@~1.2.2:
     ethereumjs-util "^4.0.1"
     ethereumjs-util "^4.0.1"
     merkle-patricia-tree "^2.1.2"
     merkle-patricia-tree "^2.1.2"
 
 
-"ethereumjs-testrpc-sc@git+https://github.com/sc-forks/testrpc-sc.git":
+"ethereumjs-testrpc-sc@https://github.com/sc-forks/testrpc-sc.git":
   version "3.0.3"
   version "3.0.3"
-  resolved "git+https://github.com/sc-forks/testrpc-sc.git#15cc0fb8e031bee152c7b8e3f8df5f2ad33ca04f"
+  resolved "https://github.com/sc-forks/testrpc-sc.git#c636f173cad9026a42a5909a768ba7e156f4abc7"
   dependencies:
   dependencies:
     async "~1.5.0"
     async "~1.5.0"
     bignumber.js "~2.1.4"
     bignumber.js "~2.1.4"
-    bip39 "~2.2.0"
+    bip39 "2.2.0"
     ethereumjs-account "~2.0.4"
     ethereumjs-account "~2.0.4"
     ethereumjs-block "~1.2.2"
     ethereumjs-block "~1.2.2"
     ethereumjs-tx "1.1.2"
     ethereumjs-tx "1.1.2"
@@ -1834,7 +2058,7 @@ ethereumjs-block@~1.2.2:
     merkle-patricia-tree "~2.1.2"
     merkle-patricia-tree "~2.1.2"
     seedrandom "~2.4.2"
     seedrandom "~2.4.2"
     shelljs "~0.6.0"
     shelljs "~0.6.0"
-    solc "0.4.6"
+    solc "0.4.8"
     temp "^0.8.3"
     temp "^0.8.3"
     tmp "0.0.31"
     tmp "0.0.31"
     web3 "~0.16.0"
     web3 "~0.16.0"
@@ -1972,12 +2196,23 @@ ethpm@0.0.10:
     semver "^5.3.0"
     semver "^5.3.0"
     wget-improved "^1.4.0"
     wget-improved "^1.4.0"
 
 
+event-emitter@~0.3.5:
+  version "0.3.5"
+  resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
+  dependencies:
+    d "1"
+    es5-ext "~0.10.14"
+
 evp_bytestokey@^1.0.0:
 evp_bytestokey@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz#497b66ad9fef65cd7c08a6180824ba1476b66e53"
   resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz#497b66ad9fef65cd7c08a6180824ba1476b66e53"
   dependencies:
   dependencies:
     create-hash "^1.1.1"
     create-hash "^1.1.1"
 
 
+exit-hook@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
+
 expand-brackets@^0.1.4:
 expand-brackets@^0.1.4:
   version "0.1.5"
   version "0.1.5"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -2031,6 +2266,20 @@ fast-levenshtein@~2.0.4:
   version "2.0.6"
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
 
 
+figures@^1.3.5:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
+  dependencies:
+    escape-string-regexp "^1.0.5"
+    object-assign "^4.1.0"
+
+file-entry-cache@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
+  dependencies:
+    flat-cache "^1.2.1"
+    object-assign "^4.0.1"
+
 filename-regex@^2.0.0:
 filename-regex@^2.0.0:
   version "2.0.1"
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@@ -2071,6 +2320,15 @@ find-up@^2.0.0, find-up@^2.1.0:
   dependencies:
   dependencies:
     locate-path "^2.0.0"
     locate-path "^2.0.0"
 
 
+flat-cache@^1.2.1:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
+  dependencies:
+    circular-json "^0.3.1"
+    del "^2.0.2"
+    graceful-fs "^4.1.2"
+    write "^0.2.1"
+
 flatmap@0.0.3:
 flatmap@0.0.3:
   version "0.0.3"
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4"
   resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4"
@@ -2226,6 +2484,10 @@ get-caller-file@^1.0.1:
   version "1.0.2"
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
 
 
+get-func-name@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
+
 getpass@^0.1.1:
 getpass@^0.1.1:
   version "0.1.7"
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
   resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
@@ -2314,7 +2576,7 @@ global@~4.3.0:
     min-document "^2.19.0"
     min-document "^2.19.0"
     process "~0.5.1"
     process "~0.5.1"
 
 
-globals@^9.0.0:
+globals@^9.0.0, globals@^9.14.0:
   version "9.18.0"
   version "9.18.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
   resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
 
 
@@ -2570,6 +2832,10 @@ ieee754@^1.1.8:
   version "1.1.8"
   version "1.1.8"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
 
 
+ignore@^3.2.0:
+  version "3.3.3"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
+
 immediate@^3.2.3:
 immediate@^3.2.3:
   version "3.2.3"
   version "3.2.3"
   resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
   resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
@@ -2597,6 +2863,24 @@ ini@~1.3.0:
   version "1.3.4"
   version "1.3.4"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
 
 
+inquirer@^0.12.0:
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
+  dependencies:
+    ansi-escapes "^1.1.0"
+    ansi-regex "^2.0.0"
+    chalk "^1.0.0"
+    cli-cursor "^1.0.1"
+    cli-width "^2.0.0"
+    figures "^1.3.5"
+    lodash "^4.3.0"
+    readline2 "^1.0.1"
+    run-async "^0.1.0"
+    rx-lite "^3.1.2"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.0"
+    through "^2.3.6"
+
 interface-connection@^0.3.0, interface-connection@~0.3.1, interface-connection@~0.3.2:
 interface-connection@^0.3.0, interface-connection@~0.3.1, interface-connection@~0.3.2:
   version "0.3.2"
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/interface-connection/-/interface-connection-0.3.2.tgz#e4949883f6ea79fb7edd01ee3f4fca47a29fd2c4"
   resolved "https://registry.yarnpkg.com/interface-connection/-/interface-connection-0.3.2.tgz#e4949883f6ea79fb7edd01ee3f4fca47a29fd2c4"
@@ -2949,6 +3233,10 @@ is-fullwidth-code-point@^1.0.0:
   dependencies:
   dependencies:
     number-is-nan "^1.0.0"
     number-is-nan "^1.0.0"
 
 
+is-fullwidth-code-point@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+
 is-function@^1.0.1, is-function@~1.0.0:
 is-function@^1.0.1, is-function@~1.0.0:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
   resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
@@ -2977,7 +3265,7 @@ is-ipfs@~0.3.0:
     bs58 "^4.0.0"
     bs58 "^4.0.0"
     multihashes "^0.3.2"
     multihashes "^0.3.2"
 
 
-is-my-json-valid@^2.12.4:
+is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4:
   version "2.16.0"
   version "2.16.0"
   resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
   resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
   dependencies:
   dependencies:
@@ -3048,6 +3336,12 @@ is-regex@^1.0.3:
   dependencies:
   dependencies:
     has "^1.0.1"
     has "^1.0.1"
 
 
+is-resolvable@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
+  dependencies:
+    tryit "^1.0.1"
+
 is-retry-allowed@^1.0.0:
 is-retry-allowed@^1.0.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
   resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
@@ -3072,7 +3366,7 @@ isarray@0.0.1:
   version "0.0.1"
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
 
 
-isarray@1.0.0, isarray@~1.0.0:
+isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
 
 
@@ -3170,7 +3464,7 @@ js-tokens@^3.0.0:
   version "3.0.1"
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
 
 
-js-yaml@3.6.1, js-yaml@3.x:
+js-yaml@3.6.1, js-yaml@3.x, js-yaml@^3.5.1:
   version "3.6.1"
   version "3.6.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
   dependencies:
   dependencies:
@@ -3201,7 +3495,7 @@ json-schema@0.2.3:
   version "0.2.3"
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
 
 
-json-stable-stringify@^1.0.1:
+json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
   version "1.0.1"
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
   resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
   dependencies:
   dependencies:
@@ -3422,7 +3716,7 @@ levelup@~0.19.0:
     semver "~5.1.0"
     semver "~5.1.0"
     xtend "~3.0.0"
     xtend "~3.0.0"
 
 
-levn@~0.3.0:
+levn@^0.3.0, levn@~0.3.0:
   version "0.3.0"
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
   resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
   dependencies:
   dependencies:
@@ -3754,7 +4048,7 @@ lodash.values@^4.3.0:
   version "4.3.0"
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
   resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
 
 
-lodash@^4.11.1, lodash@^4.11.2, lodash@^4.14.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.5.1:
+lodash@^4.0.0, lodash@^4.11.1, lodash@^4.11.2, lodash@^4.14.0, lodash@^4.17.1, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1:
   version "4.17.4"
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
 
 
@@ -3955,7 +4249,7 @@ mocha@^3.2.0:
     mkdirp "0.5.1"
     mkdirp "0.5.1"
     supports-color "3.1.2"
     supports-color "3.1.2"
 
 
-moment@2.x.x:
+moment@2.x.x, moment@^2.18.1:
   version "2.18.1"
   version "2.18.1"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
 
 
@@ -4073,10 +4367,18 @@ murmurhash3js@^3.0.1:
   version "3.0.1"
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/murmurhash3js/-/murmurhash3js-3.0.1.tgz#3e983e5b47c2a06f43a713174e7e435ca044b998"
   resolved "https://registry.yarnpkg.com/murmurhash3js/-/murmurhash3js-3.0.1.tgz#3e983e5b47c2a06f43a713174e7e435ca044b998"
 
 
+mute-stream@0.0.5:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0"
+
 nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.5.1, nan@~2.6.1:
 nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.5.1, nan@~2.6.1:
   version "2.6.2"
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
 
 
+natural-compare@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+
 ndjson@^1.4.3:
 ndjson@^1.4.3:
   version "1.5.0"
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-1.5.0.tgz#ae603b36b134bcec347b452422b0bf98d5832ec8"
   resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-1.5.0.tgz#ae603b36b134bcec347b452422b0bf98d5832ec8"
@@ -4274,6 +4576,10 @@ once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0:
   dependencies:
   dependencies:
     wrappy "1"
     wrappy "1"
 
 
+onetime@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
+
 optimist@^0.6.1:
 optimist@^0.6.1:
   version "0.6.1"
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
   resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
@@ -4287,7 +4593,7 @@ optimist@~0.3.5:
   dependencies:
   dependencies:
     wordwrap "~0.0.2"
     wordwrap "~0.0.2"
 
 
-optionator@^0.8.1:
+optionator@^0.8.1, optionator@^0.8.2:
   version "0.8.2"
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
   dependencies:
   dependencies:
@@ -4430,6 +4736,10 @@ path-type@^2.0.0:
   dependencies:
   dependencies:
     pify "^2.0.0"
     pify "^2.0.0"
 
 
+pathval@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
+
 pbkdf2@^3.0.0, pbkdf2@^3.0.3, pbkdf2@^3.0.9:
 pbkdf2@^3.0.0, pbkdf2@^3.0.3, pbkdf2@^3.0.9:
   version "3.0.12"
   version "3.0.12"
   resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.12.tgz#be36785c5067ea48d806ff923288c5f750b6b8a2"
   resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.12.tgz#be36785c5067ea48d806ff923288c5f750b6b8a2"
@@ -4501,6 +4811,10 @@ pinkie@^2.0.0:
   version "2.0.4"
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
 
 
+pluralize@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45"
+
 podium@^1.2.x:
 podium@^1.2.x:
   version "1.2.5"
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/podium/-/podium-1.2.5.tgz#87c566c2f0365bcf0a1ec7602c4d01948cdd2ad5"
   resolved "https://registry.yarnpkg.com/podium/-/podium-1.2.5.tgz#87c566c2f0365bcf0a1ec7602c4d01948cdd2ad5"
@@ -4552,6 +4866,10 @@ process@~0.5.1:
   version "0.5.2"
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
   resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
 
 
+progress@^1.1.8:
+  version "1.1.8"
+  resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
+
 promise@~1.3.0:
 promise@~1.3.0:
   version "1.3.0"
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/promise/-/promise-1.3.0.tgz#e5cc9a4c8278e4664ffedc01c7da84842b040175"
   resolved "https://registry.yarnpkg.com/promise/-/promise-1.3.0.tgz#e5cc9a4c8278e4664ffedc01c7da84842b040175"
@@ -4869,6 +5187,14 @@ readdirp@^2.0.0:
     readable-stream "^2.0.2"
     readable-stream "^2.0.2"
     set-immediate-shim "^1.0.1"
     set-immediate-shim "^1.0.1"
 
 
+readline2@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    mute-stream "0.0.5"
+
 rechoir@^0.6.2:
 rechoir@^0.6.2:
   version "0.6.2"
   version "0.6.2"
   resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
   resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
@@ -5031,6 +5357,17 @@ require-nocache@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/require-nocache/-/require-nocache-1.0.0.tgz#a665d0b60a07e8249875790a4d350219d3c85fa3"
   resolved "https://registry.yarnpkg.com/require-nocache/-/require-nocache-1.0.0.tgz#a665d0b60a07e8249875790a4d350219d3c85fa3"
 
 
+require-uncached@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
+  dependencies:
+    caller-path "^0.1.0"
+    resolve-from "^1.0.0"
+
+resolve-from@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+
 resolve-from@^2.0.0:
 resolve-from@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
@@ -5039,6 +5376,13 @@ resolve@1.1.x, resolve@^1.1.5, resolve@^1.1.6, resolve@~1.1.7:
   version "1.1.7"
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
 
 
+restore-cursor@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
+  dependencies:
+    exit-hook "^1.0.0"
+    onetime "^1.0.0"
+
 resumer@~0.0.0:
 resumer@~0.0.0:
   version "0.0.0"
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759"
   resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759"
@@ -5091,6 +5435,12 @@ rsa-unpack@0.0.6:
   dependencies:
   dependencies:
     optimist "~0.3.5"
     optimist "~0.3.5"
 
 
+run-async@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
+  dependencies:
+    once "^1.3.0"
+
 run-parallel-limit@^1.0.3:
 run-parallel-limit@^1.0.3:
   version "1.0.3"
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.0.3.tgz#6c3930cc7c0b47d35ae7420109f660aade2401e3"
   resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.0.3.tgz#6c3930cc7c0b47d35ae7420109f660aade2401e3"
@@ -5099,6 +5449,10 @@ run-series@^1.1.4:
   version "1.1.4"
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.4.tgz#89a73ddc5e75c9ef8ab6320c0a1600d6a41179b9"
   resolved "https://registry.yarnpkg.com/run-series/-/run-series-1.1.4.tgz#89a73ddc5e75c9ef8ab6320c0a1600d6a41179b9"
 
 
+rx-lite@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+
 safe-buffer@^5.0.1, safe-buffer@^5.1.0:
 safe-buffer@^5.0.1, safe-buffer@^5.1.0:
   version "5.1.0"
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223"
@@ -5221,7 +5575,7 @@ shallow-copy@~0.0.1:
   version "0.0.1"
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
   resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
 
 
-shelljs@^0.7.4:
+shelljs@^0.7.4, shelljs@^0.7.5:
   version "0.7.8"
   version "0.7.8"
   resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
   resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
   dependencies:
   dependencies:
@@ -5276,6 +5630,10 @@ slash@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
 
 
+slice-ansi@0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+
 slide@^1.1.5:
 slide@^1.1.5:
   version "1.1.6"
   version "1.1.6"
   resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
   resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
@@ -5344,18 +5702,19 @@ solc@0.4.11, solc@^0.4.2:
     semver "^5.3.0"
     semver "^5.3.0"
     yargs "^4.7.1"
     yargs "^4.7.1"
 
 
-solc@0.4.6:
-  version "0.4.6"
-  resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.6.tgz#afa929a1ceafc0252cfbb4217c8e2b1dab139db7"
+solc@0.4.8:
+  version "0.4.8"
+  resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.8.tgz#96abbee1266341ae97fb4bdc3abcc9bc1b5052ab"
   dependencies:
   dependencies:
     fs-extra "^0.30.0"
     fs-extra "^0.30.0"
     memorystream "^0.3.1"
     memorystream "^0.3.1"
     require-from-string "^1.1.0"
     require-from-string "^1.1.0"
+    semver "^5.3.0"
     yargs "^4.7.1"
     yargs "^4.7.1"
 
 
-solidity-coverage@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.1.0.tgz#e0f30319399dfe3a346f612e4f2a10361fe9e9c8"
+solidity-coverage@^0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.1.7.tgz#dd83d0685fc3bb107355da3b7da2db576bbc7374"
   dependencies:
   dependencies:
     commander "^2.9.0"
     commander "^2.9.0"
     ethereumjs-testrpc-sc "https://github.com/sc-forks/testrpc-sc.git"
     ethereumjs-testrpc-sc "https://github.com/sc-forks/testrpc-sc.git"
@@ -5365,11 +5724,11 @@ solidity-coverage@^0.1.0:
     req-cwd "^1.0.1"
     req-cwd "^1.0.1"
     shelljs "^0.7.4"
     shelljs "^0.7.4"
     sol-explore "^1.6.2"
     sol-explore "^1.6.2"
-    solidity-parser "0.3.0"
+    solidity-parser "git+https://github.com/sc-forks/solidity-parser.git"
 
 
-solidity-parser@0.3.0, solidity-parser@^0.3.0:
+solidity-parser@^0.3.0, "solidity-parser@git+https://github.com/sc-forks/solidity-parser.git":
   version "0.3.0"
   version "0.3.0"
-  resolved "https://registry.yarnpkg.com/solidity-parser/-/solidity-parser-0.3.0.tgz#cab04f8e406bdc1f3c16512eec6aa87a1072f8b9"
+  resolved "git+https://github.com/sc-forks/solidity-parser.git#6c544bd308fb6d38b2ca7e2adde9a42334221ab0"
   dependencies:
   dependencies:
     mocha "^2.4.5"
     mocha "^2.4.5"
     pegjs "^0.10.0"
     pegjs "^0.10.0"
@@ -5541,6 +5900,13 @@ string-width@^1.0.1, string-width@^1.0.2:
     is-fullwidth-code-point "^1.0.0"
     is-fullwidth-code-point "^1.0.0"
     strip-ansi "^3.0.0"
     strip-ansi "^3.0.0"
 
 
+string-width@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.0.tgz#030664561fc146c9423ec7d978fe2457437fe6d0"
+  dependencies:
+    is-fullwidth-code-point "^2.0.0"
+    strip-ansi "^4.0.0"
+
 string.prototype.trim@~1.1.2:
 string.prototype.trim@~1.1.2:
   version "1.1.2"
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
   resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
@@ -5569,6 +5935,12 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
   dependencies:
   dependencies:
     ansi-regex "^2.0.0"
     ansi-regex "^2.0.0"
 
 
+strip-ansi@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+  dependencies:
+    ansi-regex "^3.0.0"
+
 strip-bom@^2.0.0:
 strip-bom@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
@@ -5603,7 +5975,7 @@ supports-color@1.2.0:
   version "1.2.0"
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e"
 
 
-supports-color@3.1.2:
+supports-color@3.1.2, supports-color@^3.1.0:
   version "3.1.2"
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
   dependencies:
   dependencies:
@@ -5613,11 +5985,16 @@ supports-color@^2.0.0:
   version "2.0.0"
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
 
 
-supports-color@^3.1.0:
-  version "3.2.3"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+table@^3.7.8:
+  version "3.8.3"
+  resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
   dependencies:
   dependencies:
-    has-flag "^1.0.0"
+    ajv "^4.7.0"
+    ajv-keywords "^1.0.0"
+    chalk "^1.1.1"
+    lodash "^4.0.0"
+    slice-ansi "0.0.4"
+    string-width "^2.0.0"
 
 
 tape@^4.4.0:
 tape@^4.4.0:
   version "4.6.3"
   version "4.6.3"
@@ -5683,6 +6060,10 @@ temp@^0.8.3:
     os-tmpdir "^1.0.0"
     os-tmpdir "^1.0.0"
     rimraf "~2.2.6"
     rimraf "~2.2.6"
 
 
+text-table@~0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+
 through2@^2.0.0, through2@^2.0.1, through2@^2.0.2, through2@^2.0.3:
 through2@^2.0.0, through2@^2.0.1, through2@^2.0.2, through2@^2.0.3:
   version "2.0.3"
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
@@ -5697,7 +6078,7 @@ through2@~0.4.1:
     readable-stream "~1.0.17"
     readable-stream "~1.0.17"
     xtend "~2.1.1"
     xtend "~2.1.1"
 
 
-through@~2.3.4, through@~2.3.8:
+through@^2.3.6, through@~2.3.4, through@~2.3.8:
   version "2.3.8"
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
 
 
@@ -5958,6 +6339,10 @@ truffle@3.2.2:
     web3 "^0.18.0"
     web3 "^0.18.0"
     yargs "^6.6.0"
     yargs "^6.6.0"
 
 
+tryit@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
+
 tslib@^1.5.0:
 tslib@^1.5.0:
   version "1.7.1"
   version "1.7.1"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec"
@@ -5998,6 +6383,14 @@ type-detect@^1.0.0:
   version "1.0.0"
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
 
 
+type-detect@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55"
+
+type-detect@^4.0.0:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
+
 typedarray-to-buffer@^3.1.2:
 typedarray-to-buffer@^3.1.2:
   version "3.1.2"
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz#1017b32d984ff556eba100f501589aba1ace2e04"
   resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz#1017b32d984ff556eba100f501589aba1ace2e04"
@@ -6086,6 +6479,12 @@ user-home@^1.1.1:
   version "1.1.1"
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
   resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
 
 
+user-home@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f"
+  dependencies:
+    os-homedir "^1.0.0"
+
 utf8@^2.1.1:
 utf8@^2.1.1:
   version "2.1.2"
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96"
   resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96"
@@ -6296,6 +6695,12 @@ write-file-atomic@^1.1.2:
     imurmurhash "^0.1.4"
     imurmurhash "^0.1.4"
     slide "^1.1.5"
     slide "^1.1.5"
 
 
+write@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+  dependencies:
+    mkdirp "^0.5.1"
+
 ws@1.1.2:
 ws@1.1.2:
   version "1.1.2"
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f"
   resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f"