Browse Source

Merge branch 'master' into fix/docs

Alejandro Santander 8 years ago
parent
commit
689e18aab5

+ 6 - 0
.travis.yml

@@ -15,3 +15,9 @@ matrix:
     - env: SOLIDITY_COVERAGE=true
 script:
   - yarn test
+notifications:
+  slack:
+    rooms:
+      - secure: uEhwUkuwJp5pBNh+VTEytPHz3FDKsnPrKO+8MTAKv5hKi4PCRoVhLv6pklr82HUpL6pvSvJbUPA0HVebOXA+MMSxdny/BHZTh2mtw5Y78l2Ad0svDTWuV2Lus2pmhYigRhT0Wo00/SRX9+pxm0kg4EIFJSTS+uR9G76x0l9NljpEGXrqxlDxjxoHBgk8Ciru2LHaLzX/utE3jlABts4Sb1F3wc2BwFkjd6BDCRTGAPhVJwwFk41ZfnmLVbgSNUyk46Cb38oG5oXHb0FI3d3jV/k1OUhRyFfmA2fLXRk0wavibW8TG1gGJJWZ7xTCKzw/Cvup6mpehSAeQef8eekMdjpWEhF9hYRq1BvOs0384UU8NQ0O+BtdXU+X3Nyr84TMJN/iIfgN7gYX7AsvXH3jC0JfNUcIkWlJvyXdE6l2GV1hMmhL09GFEBbSpuSXRIWlOXTcYBlp5NbvE8xO8PUW+T6N5RG2XXjv1g8wCpr6Wwk1+LmRkX5trv8MFBZ2pM8p4H5da5++Ov8egLonNGK2jbx6aBLBX3tPf+g70LZEkiQ4eBfZw8VIgXIvKreisicppNuCD27gNmSEPNt0NkwiEBcTCJ9GSVAO0CU2g4ggvHDX2A+RW5XPET9bGkBXKLfFyV7Qe+MSQjXkCnW3bIRh7Wo1V31XiUiYOLuZPIiH3EQ=
+    on_success: change
+    on_failure: always

+ 2 - 2
contracts/crowdsale/Crowdsale.sol

@@ -44,7 +44,7 @@ contract Crowdsale {
     require(_startTime >= now);
     require(_endTime >= _startTime);
     require(_rate > 0);
-    require(_wallet != 0x0);
+    require(_wallet != address(0));
 
     token = createTokenContract();
     startTime = _startTime;
@@ -67,7 +67,7 @@ contract Crowdsale {
 
   // low level token purchase function
   function buyTokens(address beneficiary) public payable {
-    require(beneficiary != 0x0);
+    require(beneficiary != address(0));
     require(validPurchase());
 
     uint256 weiAmount = msg.value;

+ 1 - 1
contracts/crowdsale/RefundVault.sol

@@ -23,7 +23,7 @@ contract RefundVault is Ownable {
   event Refunded(address indexed beneficiary, uint256 weiAmount);
 
   function RefundVault(address _wallet) {
-    require(_wallet != 0x0);
+    require(_wallet != address(0));
     wallet = _wallet;
     state = State.Active;
   }

+ 4 - 1
contracts/math/SafeMath.sol

@@ -7,8 +7,11 @@ pragma solidity ^0.4.11;
  */
 library SafeMath {
   function mul(uint256 a, uint256 b) internal constant returns (uint256) {
+    if (a == 0) {
+      return 0;
+    }
     uint256 c = a * b;
-    assert(a == 0 || c / a == b);
+    assert(c / a == b);
     return c;
   }
 

+ 1 - 1
contracts/ownership/Claimable.sol

@@ -34,6 +34,6 @@ contract Claimable is Ownable {
   function claimOwnership() onlyPendingOwner public {
     OwnershipTransferred(owner, pendingOwner);
     owner = pendingOwner;
-    pendingOwner = 0x0;
+    pendingOwner = address(0);
   }
 }

+ 1 - 1
contracts/ownership/DelayedClaimable.sol

@@ -35,7 +35,7 @@ contract DelayedClaimable is Claimable {
     require((block.number <= end) && (block.number >= start));
     OwnershipTransferred(owner, pendingOwner);
     owner = pendingOwner;
-    pendingOwner = 0x0;
+    pendingOwner = address(0);
     end = 0;
   }
 

+ 65 - 0
contracts/payment/SplitPayment.sol

@@ -0,0 +1,65 @@
+pragma solidity ^0.4.11;
+
+import '../math/SafeMath.sol';
+
+/**
+ * @title SplitPayment
+ * @dev Base contract that supports multiple payees claiming funds sent to this contract 
+ * according to the proportion they own.
+ */
+contract SplitPayment {
+  using SafeMath for uint256;
+
+  uint256 public totalShares = 0;
+  uint256 public totalReleased = 0;
+
+  mapping(address => uint256) public shares;
+  mapping(address => uint256) public released;
+  address[] public payees;
+
+  /**
+   * @dev Constructor
+   */
+  function SplitPayment(address[] _payees, uint256[] _shares) {
+    require(_payees.length == _shares.length);
+
+    for (uint256 i = 0; i < _payees.length; i++) {
+      addPayee(_payees[i], _shares[i]);
+    }
+  }
+
+  /**
+   * @dev Add a new payee to the contract.
+   * @param _payee The address of the payee to add.
+   * @param _shares The number of shares owned by the payee.
+   */
+  function addPayee(address _payee, uint256 _shares) internal {
+    require(_payee != address(0));
+    require(_shares > 0);
+    require(shares[_payee] == 0);
+
+    payees.push(_payee);
+    shares[_payee] = _shares;
+    totalShares = totalShares.add(_shares);
+  }
+
+  /**
+   * @dev Claim your share of the balance.
+   */
+  function claim() public {
+    address payee = msg.sender;
+
+    require(shares[payee] > 0);
+
+    uint256 totalReceived = this.balance.add(totalReleased);
+    uint256 payment = totalReceived.mul(shares[payee]).div(totalShares).sub(released[payee]);
+
+    require(payment != 0);
+    require(this.balance >= payment);
+
+    released[payee] = released[payee].add(payment);
+    totalReleased = totalReleased.add(payment);
+
+    payee.transfer(payment);
+  }
+}

+ 15 - 0
contracts/token/DetailedERC20.sol

@@ -0,0 +1,15 @@
+pragma solidity ^0.4.11;
+
+import './ERC20.sol';
+
+contract DetailedERC20 is ERC20 {
+  string public name;
+  string public symbol;
+  uint8 public decimals;
+
+  function DetailedERC20(string _name, string _symbol, uint8 _decimals) {
+    name = _name;
+    symbol = _symbol;
+    decimals = _decimals;
+  }
+}

+ 2 - 2
contracts/token/MintableToken.sol

@@ -35,7 +35,7 @@ contract MintableToken is StandardToken, Ownable {
     totalSupply = totalSupply.add(_amount);
     balances[_to] = balances[_to].add(_amount);
     Mint(_to, _amount);
-    Transfer(0x0, _to, _amount);
+    Transfer(address(0), _to, _amount);
     return true;
   }
 
@@ -43,7 +43,7 @@ contract MintableToken is StandardToken, Ownable {
    * @dev Function to stop minting new tokens.
    * @return True if the operation was successful.
    */
-  function finishMinting() onlyOwner public returns (bool) {
+  function finishMinting() onlyOwner canMint public returns (bool) {
     mintingFinished = true;
     MintFinished();
     return true;

+ 0 - 9
contracts/token/TokenTimelock.sol

@@ -28,15 +28,6 @@ contract TokenTimelock {
     releaseTime = _releaseTime;
   }
 
-  /**
-   * @notice Transfers tokens held by timelock to beneficiary.
-   * Deprecated: please use TokenTimelock#release instead.
-   */
-  function claim() public {
-    require(msg.sender == beneficiary);
-    release();
-  }
-
   /**
    * @notice Transfers tokens held by timelock to beneficiary.
    */

+ 41 - 30
contracts/token/TokenVesting.sol

@@ -1,8 +1,8 @@
 pragma solidity ^0.4.11;
 
 import './ERC20Basic.sol';
+import './SafeERC20.sol';
 import '../ownership/Ownable.sol';
-import '../math/Math.sol';
 import '../math/SafeMath.sol';
 
 /**
@@ -13,20 +13,22 @@ import '../math/SafeMath.sol';
  */
 contract TokenVesting is Ownable {
   using SafeMath for uint256;
+  using SafeERC20 for ERC20Basic;
 
   event Released(uint256 amount);
   event Revoked();
 
   // beneficiary of tokens after they are released
-  address beneficiary;
+  address public beneficiary;
 
-  uint256 cliff;
-  uint256 start;
-  uint256 duration;
+  uint256 public cliff;
+  uint256 public start;
+  uint256 public duration;
 
-  bool revocable;
+  bool public revocable;
 
-  mapping (address => uint256) released;
+  mapping (address => uint256) public released;
+  mapping (address => bool) public revoked;
 
   /**
    * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
@@ -38,13 +40,13 @@ contract TokenVesting is Ownable {
    * @param _revocable whether the vesting is revocable or not
    */
   function TokenVesting(address _beneficiary, uint256 _start, uint256 _cliff, uint256 _duration, bool _revocable) {
-    require(_beneficiary != 0x0);
+    require(_beneficiary != address(0));
     require(_cliff <= _duration);
 
     beneficiary = _beneficiary;
     revocable = _revocable;
     duration = _duration;
-    cliff = _start + _cliff;
+    cliff = _start.add(_cliff);
     start = _start;
   }
 
@@ -52,30 +54,35 @@ contract TokenVesting is Ownable {
    * @notice Transfers vested tokens to beneficiary.
    * @param token ERC20 token which is being vested
    */
-  function release(ERC20Basic token) {
-    uint256 vested = vestedAmount(token);
+  function release(ERC20Basic token) public {
+    uint256 unreleased = releasableAmount(token);
 
-    require(vested > 0);
+    require(unreleased > 0);
 
-    token.transfer(beneficiary, vested);
+    released[token] = released[token].add(unreleased);
 
-    released[token] = released[token].add(vested);
+    token.safeTransfer(beneficiary, unreleased);
 
-    Released(vested);
+    Released(unreleased);
   }
 
   /**
-   * @notice Allows the owner to revoke the vesting. Tokens already vested remain in the contract.
+   * @notice Allows the owner to revoke the vesting. Tokens already vested
+   * remain in the contract, the rest are returned to the owner.
    * @param token ERC20 token which is being vested
    */
-  function revoke(ERC20Basic token) onlyOwner {
+  function revoke(ERC20Basic token) public onlyOwner {
     require(revocable);
+    require(!revoked[token]);
 
     uint256 balance = token.balanceOf(this);
 
-    uint256 vested = vestedAmount(token);
+    uint256 unreleased = releasableAmount(token);
+    uint256 refund = balance.sub(unreleased);
 
-    token.transfer(owner, balance - vested);
+    revoked[token] = true;
+
+    token.safeTransfer(owner, refund);
 
     Revoked();
   }
@@ -84,20 +91,24 @@ contract TokenVesting is Ownable {
    * @dev Calculates the amount that has already vested but hasn't been released yet.
    * @param token ERC20 token which is being vested
    */
-  function vestedAmount(ERC20Basic token) constant returns (uint256) {
+  function releasableAmount(ERC20Basic token) public constant returns (uint256) {
+    return vestedAmount(token).sub(released[token]);
+  }
+
+  /**
+   * @dev Calculates the amount that has already vested.
+   * @param token ERC20 token which is being vested
+   */
+  function vestedAmount(ERC20Basic token) public constant returns (uint256) {
+    uint256 currentBalance = token.balanceOf(this);
+    uint256 totalBalance = currentBalance.add(released[token]);
+
     if (now < cliff) {
       return 0;
-    } else if (now >= start + duration) {
-      return token.balanceOf(this);
+    } else if (now >= start.add(duration) || revoked[token]) {
+      return totalBalance;
     } else {
-      uint256 currentBalance = token.balanceOf(this);
-      uint256 totalBalance = currentBalance.add(released[token]);
-
-      uint256 vested = totalBalance.mul(now - start).div(duration);
-      uint256 unreleased = vested.sub(released[token]);
-
-      // currentBalance can be 0 in case of vesting being revoked earlier.
-      return Math.min256(currentBalance, unreleased);
+      return totalBalance.mul(now.sub(start)).div(duration);
     }
   }
 }

+ 4 - 4
docs/source/bounty.rst

@@ -7,14 +7,14 @@ To create a bounty for your contract, inherit from the base `Bounty` contract an
 	import "./YourContract.sol";
 
 	contract YourBounty is Bounty {
-	function deployContract() internal returns(address) {
-	return new YourContract()
+	  function deployContract() internal returns(address) {
+	    return new YourContract()
 	  }
 	}
 
 
 Next, implement invariant logic into your smart contract.
-Your main contract should inherit from the Target class and implement the checkInvariant method. This is a function that should check everything your contract assumes to be true all the time. If this function returns false, it means your contract was broken in some way and is in an inconsistent state. This is what security researchers will try to acomplish when trying to get the bounty.
+Your main contract should inherit from the `Target` class and implement the ```checkInvariant()``` method. This is a function that should check everything your contract assumes to be true all the time. If this function returns false, it means your contract was broken in some way and is in an inconsistent state. This is what security researchers will try to acomplish when trying to get the bounty.
 
 At contracts/YourContract.sol::
 
@@ -35,7 +35,7 @@ At ```migrations/2_deploy_contracts.js```::
 	  deployer.deploy(YourBounty);
 	};
 
-Next, add a reward to the bounty contract
+Next, add a reward to the bounty contract.
 
 After deploying the contract, send reward funds into the bounty contract.
 

+ 2 - 2
docs/source/ecrecovery.rst

@@ -1,7 +1,7 @@
-ECReovery
+ECRecovery
 =============================================
 
-Returns the signer of the the hash using the signature divided in v, r, and s values.
+Returns the signer of the hash using the signature divided in v, r, and s values.
 
 recover(bytes32 hash, bytes sig) internal returns (address)
 """""""""""""""""""""""""""""""""""""""""""""""""

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

@@ -9,6 +9,7 @@ OpenZeppelin integrates with `Truffle <https://github.com/ConsenSys/truffle/>`_,
 
 To install the OpenZeppelin library, run::
 
+	npm init # follow instructions
 	npm install zeppelin-solidity
 
 	# If you are using yarn, add dependency like this -

+ 10 - 10
package-lock.json

@@ -1,6 +1,6 @@
 {
   "name": "zeppelin-solidity",
-  "version": "1.2.0",
+  "version": "1.3.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -5084,15 +5084,6 @@
         "xtend": "4.0.1"
       }
     },
-    "string_decoder": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
-      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.1"
-      }
-    },
     "string-width": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@@ -5115,6 +5106,15 @@
         "function-bind": "1.1.0"
       }
     },
+    "string_decoder": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
     "stringstream": {
       "version": "0.0.5",
       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",

+ 4 - 3
test/DayLimit.js

@@ -1,16 +1,17 @@
 'use strict';
 const assertJump = require('./helpers/assertJump');
-const timer = require('./helpers/timer');
+import latestTime from './helpers/latestTime'
+import {increaseTimeTo, duration} from './helpers/increaseTime'
 
 var DayLimitMock = artifacts.require('./helpers/DayLimitMock.sol');
 
 contract('DayLimit', function(accounts) {
-  const day = 60 * 60 * 24;
 
   let dayLimit;
   let initLimit = 10;
 
   beforeEach( async function() {
+    this.startTime = latestTime();
     dayLimit = await DayLimitMock.new(initLimit);
   });
 
@@ -99,7 +100,7 @@ contract('DayLimit', function(accounts) {
     spentToday = await dayLimit.spentToday();
     assert.equal(spentToday, 8);
 
-    await timer(day);
+    await increaseTimeTo(this.startTime + duration.days(1));
 
     await dayLimit.attemptSpend(3);
     spentToday = await dayLimit.spentToday();

+ 35 - 0
test/DetailedERC20.js

@@ -0,0 +1,35 @@
+const BigNumber = web3.BigNumber;
+
+require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should();
+
+const DetailedERC20Mock = artifacts.require('./helpers/DetailedERC20Mock.sol');
+
+contract('DetailedERC20', accounts => {
+  let detailedERC20 = null;
+
+  const _name = "My Detailed ERC20";
+  const _symbol = "MDT";
+  const _decimals = 18;
+
+  beforeEach(async function() {
+    detailedERC20 = await DetailedERC20Mock.new(_name, _symbol, _decimals);
+  });
+
+  it('has a name', async function () {
+    const name = await detailedERC20.name();
+    name.should.be.equal(_name);
+  });
+
+  it('has a symbol', async function () {
+    const symbol = await detailedERC20.symbol();
+    symbol.should.be.equal(_symbol);
+  });
+
+  it('has an amount of decimals', async function () {
+    const decimals = await detailedERC20.decimals();
+    decimals.should.be.bignumber.equal(_decimals)
+  });
+});

+ 78 - 0
test/SplitPayment.js

@@ -0,0 +1,78 @@
+const BigNumber = web3.BigNumber
+
+const should = require('chai')
+  .use(require('chai-as-promised'))
+  .use(require('chai-bignumber')(BigNumber))
+  .should()
+
+const EVMThrow = require('./helpers/EVMThrow.js')
+const SplitPaymentMock = artifacts.require('./helpers/SplitPaymentMock.sol')
+
+contract('SplitPayment', function ([owner, payee1, payee2, payee3, nonpayee1, payer1]) {
+  const amount = web3.toWei(1.0, 'ether')
+
+  beforeEach(async function () {
+    this.payees = [payee1, payee2, payee3]
+    this.shares = [20, 10, 70]
+
+    this.contract = await SplitPaymentMock.new(this.payees, this.shares)
+  })
+
+  it('should accept payments', async function () {
+    await web3.eth.sendTransaction({ from: owner, to: this.contract.address, value: amount })
+
+    const balance = web3.eth.getBalance(this.contract.address)
+    balance.should.be.bignumber.equal(amount)
+  })
+
+  it('should store shares if address is payee', async function () {
+    const shares = await this.contract.shares.call(payee1)
+    shares.should.be.bignumber.not.equal(0)
+  })
+
+  it('should not store shares if address is not payee', async function () {
+    const shares = await this.contract.shares.call(nonpayee1)
+    shares.should.be.bignumber.equal(0)
+  })
+
+  it('should throw if no funds to claim', async function () {
+    await this.contract.claim({from: payee1}).should.be.rejectedWith(EVMThrow)
+  })
+
+  it('should throw if non-payee want to claim', async function () {
+    await web3.eth.sendTransaction({from: payer1, to: this.contract.address, value: amount})
+    await this.contract.claim({from: nonpayee1}).should.be.rejectedWith(EVMThrow)
+  })
+  
+  it('should distribute funds to payees', async function () {
+    await web3.eth.sendTransaction({from: payer1, to: this.contract.address, value: amount})
+
+    // receive funds
+    const initBalance = web3.eth.getBalance(this.contract.address)
+    initBalance.should.be.bignumber.equal(amount)
+
+    // distribute to payees
+    const initAmount1 = web3.eth.getBalance(payee1)
+    await this.contract.claim({from: payee1})
+    const profit1 = web3.eth.getBalance(payee1) - initAmount1
+    assert(Math.abs(profit1 - web3.toWei(0.20, 'ether')) < 1e16)
+
+    const initAmount2 = web3.eth.getBalance(payee2)
+    await this.contract.claim({from: payee2})
+    const profit2 = web3.eth.getBalance(payee2) - initAmount2
+    assert(Math.abs(profit2 - web3.toWei(0.10, 'ether')) < 1e16)
+
+    const initAmount3 = web3.eth.getBalance(payee3)
+    await this.contract.claim({from: payee3})
+    const profit3 = web3.eth.getBalance(payee3) - initAmount3
+    assert(Math.abs(profit3 - web3.toWei(0.70, 'ether')) < 1e16)
+
+    // end balance should be zero
+    const endBalance = web3.eth.getBalance(this.contract.address)
+    endBalance.should.be.bignumber.equal(0)
+
+    // check correct funds released accounting
+    const totalReleased = await this.contract.totalReleased.call()
+    totalReleased.should.be.bignumber.equal(initBalance)
+  })
+})

+ 16 - 8
test/TokenVesting.js

@@ -80,28 +80,36 @@ contract('TokenVesting', function ([_, owner, beneficiary]) {
   });
 
   it('should return the non-vested tokens when revoked by owner', async function () {
-    await increaseTimeTo(this.start + this.cliff + duration.weeks(1));
-    await this.vesting.release(this.token.address);
+    await increaseTimeTo(this.start + this.cliff + duration.weeks(12));
 
     const vested = await this.vesting.vestedAmount(this.token.address);
-    const balance = await this.token.balanceOf(this.vesting.address);
 
     await this.vesting.revoke(this.token.address, { from: owner });
 
     const ownerBalance = await this.token.balanceOf(owner);
-    ownerBalance.should.bignumber.equal(balance.sub(vested));
+    ownerBalance.should.bignumber.equal(amount.sub(vested));
   });
 
   it('should keep the vested tokens when revoked by owner', async function () {
-    await increaseTimeTo(this.start + this.cliff + duration.weeks(1));
-    await this.vesting.release(this.token.address);
+    await increaseTimeTo(this.start + this.cliff + duration.weeks(12));
+
+    const vestedPre = await this.vesting.vestedAmount(this.token.address);
+
+    await this.vesting.revoke(this.token.address, { from: owner });
+
+    const vestedPost = await this.vesting.vestedAmount(this.token.address);
+
+    vestedPre.should.bignumber.equal(vestedPost);
+  });
+
+  it('should fail to be revoked a second time', async function () {
+    await increaseTimeTo(this.start + this.cliff + duration.weeks(12));
 
     const vested = await this.vesting.vestedAmount(this.token.address);
 
     await this.vesting.revoke(this.token.address, { from: owner });
 
-    const balance = await this.token.balanceOf(this.vesting.address);
-    balance.should.bignumber.equal(vested);
+    await this.vesting.revoke(this.token.address, { from: owner }).should.be.rejectedWith(EVMThrow);
   });
 
 });

+ 8 - 0
test/helpers/DetailedERC20Mock.sol

@@ -0,0 +1,8 @@
+pragma solidity ^0.4.11;
+
+import '../../contracts/token/StandardToken.sol';
+import '../../contracts/token/DetailedERC20.sol';
+
+contract DetailedERC20Mock is StandardToken, DetailedERC20 {
+  function DetailedERC20Mock(string _name, string _symbol, uint8 _decimals) DetailedERC20(_name, _symbol, _decimals) {}
+}

+ 10 - 0
test/helpers/SplitPaymentMock.sol

@@ -0,0 +1,10 @@
+pragma solidity ^0.4.11;
+
+import '../../contracts/payment/SplitPayment.sol';
+
+// mock class using SplitPayment
+contract SplitPaymentMock is SplitPayment {
+  function SplitPaymentMock(address[] _payees, uint256[] _shares) 
+    SplitPayment(_payees, _shares) payable {}
+  function () payable {}
+}

+ 2 - 1
test/helpers/expectThrow.js

@@ -10,8 +10,9 @@ export default async promise => {
     //       we distinguish this from an actual out of gas event? (The
     //       testrpc log actually show an 'invalid jump' event.)
     const outOfGas = error.message.search('out of gas') >= 0;
+    const revert = error.message.search('revert') >= 0;
     assert(
-      invalidOpcode || outOfGas,
+      invalidOpcode || outOfGas || revert,
       "Expected throw, got '" + error + "' instead",
     );
     return;

+ 0 - 15
test/helpers/timer.js

@@ -1,15 +0,0 @@
-// timer for tests specific to testrpc
-module.exports = s => {
-  return new Promise((resolve, reject) => {
-    web3.currentProvider.sendAsync({
-      jsonrpc: '2.0',
-      method: 'evm_increaseTime',
-      params: [s], // 60 seaconds, may need to be hex, I forget
-      id: new Date().getTime() // Id of the request; anything works, really
-    }, function(err) {
-      if (err) return reject(err);
-      resolve();
-    });
-    //setTimeout(() => resolve(), s * 1000 + 600) // 600ms breathing room for testrpc to sync
-  });
-};