Browse Source

Merge pull request #146 from maraoz/refactor

Refactor in preparation for audit
Manuel Aráoz 8 years ago
parent
commit
c10a2cf15c
48 changed files with 476 additions and 391 deletions
  1. 48 0
      .jshintrc
  2. 1 0
      .soliumignore
  3. 22 0
      .soliumrc.json
  4. 3 3
      .travis.yml
  5. 8 8
      contracts/Bounty.sol
  6. 9 19
      contracts/DayLimit.sol
  7. 2 12
      contracts/MultisigWallet.sol
  8. 3 1
      contracts/SafeMath.sol
  9. 11 2
      contracts/lifecycle/Pausable.sol
  10. 11 9
      contracts/ownership/DelayedClaimable.sol
  11. 5 2
      contracts/ownership/Ownable.sol
  12. 22 32
      contracts/ownership/Shareable.sol
  13. 8 2
      contracts/payment/PullPayment.sol
  14. 4 2
      contracts/token/CrowdsaleToken.sol
  15. 46 11
      contracts/token/VestedToken.sol
  16. 2 0
      migrations/1_initial_migration.js
  17. 3 7
      migrations/2_deploy_contracts.js
  18. 3 2
      package.json
  19. 13 0
      scripts/test.sh
  20. 2 0
      test/BasicToken.js
  21. 51 52
      test/Bounty.js
  22. 16 12
      test/Claimable.js
  23. 4 0
      test/DayLimit.js
  24. 52 66
      test/DelayedClaimble.js
  25. 10 45
      test/Killable.js
  26. 14 11
      test/LimitBalance.js
  27. 11 55
      test/MultisigWallet.js
  28. 12 9
      test/Ownable.js
  29. 18 14
      test/Pausable.js
  30. 2 0
      test/PullPayment.js
  31. 1 0
      test/SafeMath.js
  32. 2 0
      test/Shareable.js
  33. 1 0
      test/StandardToken.js
  34. 1 0
      test/VestedToken.js
  35. 1 1
      test/helpers/BasicTokenMock.sol
  36. 1 1
      test/helpers/DayLimitMock.sol
  37. 1 1
      test/helpers/InsecureTargetBounty.sol
  38. 1 1
      test/helpers/LimitBalanceMock.sol
  39. 1 1
      test/helpers/MultisigWalletMock.sol
  40. 1 1
      test/helpers/PausableMock.sol
  41. 1 1
      test/helpers/PullPaymentMock.sol
  42. 1 1
      test/helpers/SafeMathMock.sol
  43. 1 1
      test/helpers/SecureTargetBounty.sol
  44. 1 1
      test/helpers/ShareableMock.sol
  45. 1 1
      test/helpers/StandardTokenMock.sol
  46. 1 1
      test/helpers/VestedTokenMock.sol
  47. 34 0
      test/helpers/transactionMined.js
  48. 9 3
      truffle.js

+ 48 - 0
.jshintrc

@@ -0,0 +1,48 @@
+{
+    "bitwise": false,     // Prohibit bitwise operators (&, |, ^, etc.).
+    "browser": true,      // Standard browser globals e.g. `window`, `document`.
+    "camelcase": false,   // Permit only camelcase for `var` and `object indexes`.
+    "curly": true,        // Require {} for every new block or scope.
+    "devel": false,       // Allow development statements e.g. `console.log();`.
+    "eqeqeq": true,       // Require triple equals i.e. `===`.
+    "esnext": true,       // Allow ES.next specific features such as `const` and `let`.
+    "freeze": true,       // Forbid overwriting prototypes of native objects such as Array, Date and so on.
+    "immed": true,        // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
+    "indent": 2,          // Specify indentation spacing
+    "latedef": true,      // Prohibit variable use before definition.
+    "newcap": false,      // Require capitalization of all constructor functions e.g. `new F()`.
+    "noarg": true,        // Prohibit use of `arguments.caller` and `arguments.callee`.
+    "node": true,         // Enable globals available when code is running inside of the NodeJS runtime environment.
+    "noempty": true,      // Prohibit use of empty blocks.
+    "nonew": true,        // Prohibits the use of constructor functions for side-effects
+    "quotmark": "single", // Define quotes to string values.
+    "regexp": true,       // Prohibit `.` and `[^...]` in regular expressions.
+    "smarttabs": false,   // Supress warnings about mixed tabs and spaces
+    "strict": true,       // Require `use strict` pragma in every file.
+    "trailing": true,     // Prohibit trailing whitespaces.
+    "undef": true,        // Require all non-global variables be declared before they are used.
+    "unused": true,       // Warn unused variables.
+
+    "maxparams": 4,       // Maximum number of parameters for a function
+    "maxstatements": 15,  // Maximum number of statements in a function
+    "maxcomplexity": 10,  // Cyclomatic complexity (http://en.wikipedia.org/wiki/Cyclomatic_complexity)
+    "maxdepth": 4,        // Maximum depth of nested control structures
+    "maxlen": 120,        // Maximum number of cols in a line
+    "multistr": true,     // Allow use of multiline EOL escaping
+    "experimental": ["asyncawait", "asyncreqawait"],
+
+    "predef": [ // Extra globals.
+        "after",
+        "afterEach",
+        "before",
+        "beforeEach",
+        "define",
+        "describe",
+        "exports",
+        "it",
+        "web3",
+        "artifacts",
+        "contract",
+        "assert"
+    ]
+}

+ 1 - 0
.soliumignore

@@ -0,0 +1 @@
+node_modules

+ 22 - 0
.soliumrc.json

@@ -0,0 +1,22 @@
+{
+  "custom-rules-filename": null,
+  "rules": {
+    "imports-on-top": true,
+    "variable-declarations": true,
+    "array-declarations": true,
+    "operator-whitespace": true,
+    "lbrace": true,
+    "mixedcase": false,
+    "camelcase": true,
+    "uppercase": true,
+    "no-with": true,
+    "no-empty-blocks": true,
+    "no-unused-vars": true,
+    "double-quotes": true,
+    "blank-lines": true,
+    "indentation": true,
+    "whitespace": true,
+    "deprecated-suicide": true,
+    "pragma-on-top": true
+  }
+}

+ 3 - 3
.travis.yml

@@ -5,8 +5,8 @@ language: node_js
 node_js:
   - "6"
 before_install:
+  - npm install truffle@3.1.9 -g
   - npm i -g ethereumjs-testrpc
-  - npm i -g truffle
 script:
-  - testrpc&
-  - npm test
+  - testrpc > /dev/null &
+  - truffle test

+ 8 - 8
contracts/Bounty.sol

@@ -11,18 +11,19 @@ import './lifecycle/Killable.sol';
  * This bounty will pay out to a researcher if they break invariant logic of the contract.
  */
 contract Bounty is PullPayment, Killable {
-  Target target;
   bool public claimed;
   mapping(address => address) public researchers;
 
   event TargetCreated(address createdAddress);
 
   function() payable {
-    if (claimed) throw;
+    if (claimed) {
+      throw;
+    }
   }
 
   function createTarget() returns(Target) {
-    target = Target(deployContract());
+    Target target = Target(deployContract());
     researchers[target] = msg.sender;
     TargetCreated(target);
     return target;
@@ -30,13 +31,11 @@ contract Bounty is PullPayment, Killable {
 
   function deployContract() internal returns(address);
 
-  function checkInvariant() returns(bool){
-    return target.checkInvariant();
-  }
-
   function claim(Target target) {
     address researcher = researchers[target];
-    if (researcher == 0) throw;
+    if (researcher == 0) {
+      throw;
+    }
     // Check Target contract invariants
     if (target.checkInvariant()) {
       throw;
@@ -47,6 +46,7 @@ contract Bounty is PullPayment, Killable {
 
 }
 
+
 /*
  * Target
  * 

+ 9 - 19
contracts/DayLimit.sol

@@ -12,33 +12,18 @@ import './ownership/Shareable.sol';
  * uses is specified in the modifier.
  */
 contract DayLimit {
-  // FIELDS
 
   uint public dailyLimit;
   uint public spentToday;
   uint public lastDay;
 
 
-  // MODIFIERS
-
-  // simple modifier for daily limit.
-  modifier limitedDaily(uint _value) {
-    if (underLimit(_value))
-      _;
-  }
-
-
-  // CONSTRUCTOR
-  // stores initial daily limit and records the present day's index.
   function DayLimit(uint _limit) {
     dailyLimit = _limit;
     lastDay = today();
   }
 
-
-  // METHODS
-
-  // (re)sets the daily limit. doesn't alter the amount already spent today.
+  // sets the daily limit. doesn't alter the amount already spent today
   function _setDailyLimit(uint _newLimit) internal {
     dailyLimit = _newLimit;
   }
@@ -48,9 +33,6 @@ contract DayLimit {
     spentToday = 0;
   }
 
-
-  // INTERNAL METHODS
-
   // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and
   // returns true. otherwise just returns false.
   function underLimit(uint _value) internal returns (bool) {
@@ -72,4 +54,12 @@ contract DayLimit {
   function today() private constant returns (uint) {
     return now / 1 days;
   }
+
+
+  // simple modifier for daily limit.
+  modifier limitedDaily(uint _value) {
+    if (underLimit(_value)) {
+      _;
+    }
+  }
 }

+ 2 - 12
contracts/MultisigWallet.sol

@@ -13,27 +13,17 @@ import "./DayLimit.sol";
  * Wallet(w).from(anotherOwner).confirm(h);
  */
 contract MultisigWallet is Multisig, Shareable, DayLimit {
-  // TYPES
 
-  // Transaction structure to remember details of transaction lest it need be saved for a later call.
   struct Transaction {
     address to;
     uint value;
     bytes data;
   }
 
-
-  // CONSTRUCTOR
-
-  // just pass on the owner array to the multiowned and
-  // the limit to daylimit
-  function MultisigWallet(address[] _owners, uint _required, uint _daylimit)
-    Shareable(_owners, _required)
+  function MultisigWallet(address[] _owners, uint _required, uint _daylimit)       
+    Shareable(_owners, _required)        
     DayLimit(_daylimit) { }
 
-
-  // METHODS
-
   // kills the contract sending everything to `_to`.
   function kill(address _to) onlymanyowners(sha3(msg.data)) external {
     suicide(_to);

+ 3 - 1
contracts/SafeMath.sol

@@ -46,6 +46,8 @@ contract SafeMath {
   }
 
   function assert(bool assertion) internal {
-    if (!assertion) throw;
+    if (!assertion) {
+      throw;
+    }
   }
 }

+ 11 - 2
contracts/lifecycle/Pausable.sol

@@ -12,8 +12,17 @@ import "../ownership/Ownable.sol";
 contract Pausable is Ownable {
   bool public stopped;
 
-  modifier stopInEmergency { if (!stopped) _; }
-  modifier onlyInEmergency { if (stopped) _; }
+  modifier stopInEmergency {
+    if (!stopped) {
+      _;
+    }
+  }
+  
+  modifier onlyInEmergency {
+    if (stopped) {
+      _;
+    }
+  }
 
   // called by the owner on emergency, triggers stopped state
   function emergencyStop() external onlyOwner {

+ 11 - 9
contracts/ownership/DelayedClaimable.sol

@@ -1,30 +1,32 @@
 pragma solidity ^0.4.4;
+
+
 import './Ownable.sol';
 import './Claimable.sol';
 
+
 /*
  * DelayedClaimable
  * Extension for the Claimable contract, where the ownership needs to be claimed before/after certain block number
  */
-
 contract DelayedClaimable is Ownable, Claimable {
 
-  uint public claimBeforeBlock;
-  uint public claimAfterBlock;
+  uint public end;
+  uint public start;
 
-  function setClaimBlocks(uint _claimBeforeBlock, uint _claimAfterBlock) onlyOwner {
-    if (_claimAfterBlock > claimBeforeBlock)
+  function setLimits(uint _start, uint _end) onlyOwner {
+    if (_start > _end)
         throw;
-    claimBeforeBlock = _claimBeforeBlock;
-    claimAfterBlock = _claimAfterBlock;
+    end = _end;
+    start = _start;
   }
 
   function claimOwnership() onlyPendingOwner {
-    if ((block.number > claimBeforeBlock) || (block.number < claimAfterBlock))
+    if ((block.number > end) || (block.number < start))
         throw;
     owner = pendingOwner;
     pendingOwner = 0x0;
-    claimBeforeBlock = 0;
+    end = 0;
   }
 
 }

+ 5 - 2
contracts/ownership/Ownable.sol

@@ -15,12 +15,15 @@ contract Ownable {
   }
 
   modifier onlyOwner() {
-    if (msg.sender == owner)
+    if (msg.sender == owner) {
       _;
+    }
   }
 
   function transferOwnership(address newOwner) onlyOwner {
-    if (newOwner != address(0)) owner = newOwner;
+    if (newOwner != address(0)) {
+      owner = newOwner;
+    }
   }
 
 }

+ 22 - 32
contracts/ownership/Shareable.sol

@@ -12,8 +12,6 @@ pragma solidity ^0.4.4;
  * 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.
  */
 contract Shareable {
-  // TYPES
-
   // struct for the status of a pending operation.
   struct PendingState {
     uint yetNeeded;
@@ -21,15 +19,11 @@ contract Shareable {
     uint index;
   }
 
-
-  // FIELDS
-
   // the number of owners that must confirm the same operation before it is run.
   uint public required;
 
   // list of owners
   uint[256] owners;
-  uint constant c_maxOwners = 250;
   // index on the list of owners to allow reverse lookup
   mapping(uint => uint) ownerIndex;
   // the ongoing operations.
@@ -37,33 +31,28 @@ contract Shareable {
   bytes32[] pendingsIndex;
 
 
-  // EVENTS
-
   // this contract only has six types of events: it can accept a confirmation, in which case
   // we record owner and operation (hash) alongside it.
   event Confirmation(address owner, bytes32 operation);
   event Revoke(address owner, bytes32 operation);
 
 
-  // MODIFIERS
-
   // simple single-sig function modifier.
   modifier onlyOwner {
-    if (isOwner(msg.sender))
+    if (isOwner(msg.sender)) {
       _;
+    }
   }
 
   // multi-sig function modifier: 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.
   modifier onlymanyowners(bytes32 _operation) {
-    if (confirmAndCheck(_operation))
+    if (confirmAndCheck(_operation)) {
       _;
+    }
   }
 
-
-  // CONSTRUCTOR
-
   // constructor is given number of sigs required to do protected "onlymanyowners" transactions
   // as well as the selection of addresses capable of confirming them.
   function Shareable(address[] _owners, uint _required) {
@@ -76,14 +65,13 @@ contract Shareable {
     required = _required;
   }
 
-
-  // METHODS
-
   // Revokes a prior confirmation of the given operation
   function revoke(bytes32 _operation) external {
     uint index = ownerIndex[uint(msg.sender)];
     // make sure they're an owner
-    if (index == 0) return;
+    if (index == 0) {
+      return;
+    }
     uint ownerIndexBit = 2**index;
     var pending = pendings[_operation];
     if (pending.ownersDone & ownerIndexBit > 0) {
@@ -107,20 +95,22 @@ contract Shareable {
     uint index = ownerIndex[uint(_owner)];
 
     // make sure they're an owner
-    if (index == 0) return false;
+    if (index == 0) {
+      return false;
+    }
 
     // determine the bit to set for this owner.
     uint ownerIndexBit = 2**index;
     return !(pending.ownersDone & ownerIndexBit == 0);
   }
 
-  // INTERNAL METHODS
-
   function confirmAndCheck(bytes32 _operation) internal returns (bool) {
     // determine what index the present sender is:
     uint index = ownerIndex[uint(msg.sender)];
     // make sure they're an owner
-    if (index == 0) return;
+    if (index == 0) {
+      return;
+    }
 
     var pending = pendings[_operation];
     // if we're not yet working on this operation, switch over and reset the confirmation status.
@@ -143,21 +133,21 @@ contract Shareable {
         delete pendingsIndex[pendings[_operation].index];
         delete pendings[_operation];
         return true;
+      } else {
+        // not enough: record that this owner in particular confirmed.
+        pending.yetNeeded--;
+        pending.ownersDone |= ownerIndexBit;
       }
-      else
-        {
-          // not enough: record that this owner in particular confirmed.
-          pending.yetNeeded--;
-          pending.ownersDone |= ownerIndexBit;
-        }
     }
   }
 
   function clearPending() internal {
     uint length = pendingsIndex.length;
-    for (uint i = 0; i < length; ++i)
-    if (pendingsIndex[i] != 0)
-      delete pendings[pendingsIndex[i]];
+    for (uint i = 0; i < length; ++i) {
+      if (pendingsIndex[i] != 0) {
+        delete pendings[pendingsIndex[i]];
+      }
+    }
     delete pendingsIndex;
   }
 

+ 8 - 2
contracts/payment/PullPayment.sol

@@ -19,10 +19,16 @@ contract PullPayment {
     address payee = msg.sender;
     uint payment = payments[payee];
     
-    if (payment == 0) throw;
-    if (this.balance < payment) throw;
+    if (payment == 0) {
+      throw;
+    }
+
+    if (this.balance < payment) {
+      throw;
+    }
 
     payments[payee] = 0;
+
     if (!payee.send(payment)) {
       throw;
     }

+ 4 - 2
contracts/token/CrowdsaleToken.sol

@@ -23,7 +23,9 @@ contract CrowdsaleToken is StandardToken {
   }
   
   function createTokens(address recipient) payable {
-    if (msg.value == 0) throw;
+    if (msg.value == 0) {
+      throw;
+    }
 
     uint tokens = safeMul(msg.value, getPrice());
 
@@ -32,7 +34,7 @@ contract CrowdsaleToken is StandardToken {
   }
   
   // replace this with any other price function
-  function getPrice() constant returns (uint result){
+  function getPrice() constant returns (uint result) {
     return PRICE;
   }
 }

+ 46 - 11
contracts/token/VestedToken.sol

@@ -1,7 +1,9 @@
 pragma solidity ^0.4.8;
 
+
 import "./StandardToken.sol";
 
+
 contract VestedToken is StandardToken {
   struct TokenGrant {
     address granter;
@@ -13,10 +15,22 @@ contract VestedToken is StandardToken {
 
   mapping (address => TokenGrant[]) public grants;
 
-  function grantVestedTokens(address _to, uint256 _value, uint64 _start, uint64 _cliff, uint64 _vesting) {
-    if (_cliff < _start) throw;
-    if (_vesting < _start) throw;
-    if (_vesting < _cliff) throw;
+  function grantVestedTokens(
+    address _to,
+    uint256 _value,
+    uint64 _start,
+    uint64 _cliff,
+    uint64 _vesting) {
+
+    if (_cliff < _start) {
+      throw;
+    }
+    if (_vesting < _start) {
+      throw;
+    }
+    if (_vesting < _cliff) {
+      throw;
+    }
 
     TokenGrant memory grant = TokenGrant({start: _start, value: _value, cliff: _cliff, vesting: _vesting, granter: msg.sender});
     grants[_to].push(grant);
@@ -27,7 +41,9 @@ contract VestedToken is StandardToken {
   function revokeTokenGrant(address _holder, uint _grantId) {
     TokenGrant grant = grants[_holder][_grantId];
 
-    if (grant.granter != msg.sender) throw;
+    if (grant.granter != msg.sender) {
+      throw;
+    }
     uint256 nonVested = nonVestedTokens(grant, uint64(now));
 
     // remove grant from array
@@ -57,12 +73,29 @@ contract VestedToken is StandardToken {
   }
 
   function vestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
-    return calculateVestedTokens(grant.value, uint256(time), uint256(grant.start), uint256(grant.cliff), uint256(grant.vesting));
+    return calculateVestedTokens(
+      grant.value,
+      uint256(time),
+      uint256(grant.start),
+      uint256(grant.cliff),
+      uint256(grant.vesting)
+    );
   }
 
-  function calculateVestedTokens(uint256 tokens, uint256 time, uint256 start, uint256 cliff, uint256 vesting) constant returns (uint256 vestedTokens) {
-    if (time < cliff) return 0;
-    if (time > vesting) return tokens;
+  function calculateVestedTokens(
+    uint256 tokens,
+    uint256 time,
+    uint256 start,
+    uint256 cliff,
+    uint256 vesting) constant returns (uint256 vestedTokens)
+    {
+
+    if (time < cliff) {
+      return 0;
+    }
+    if (time > vesting) {
+      return tokens;
+    }
 
     uint256 cliffTokens = safeDiv(safeMul(tokens, safeSub(cliff, start)), safeSub(vesting, start));
     vestedTokens = cliffTokens;
@@ -94,8 +127,10 @@ contract VestedToken is StandardToken {
     return safeSub(balances[holder], nonVested);
   }
 
-  function transfer(address _to, uint _value) returns (bool success){
-    if (_value > transferableTokens(msg.sender, uint64(now))) throw;
+  function transfer(address _to, uint _value) returns (bool success) {
+    if (_value > transferableTokens(msg.sender, uint64(now))) {
+      throw;
+    }
 
     return super.transfer(_to, _value);
   }

+ 2 - 0
migrations/1_initial_migration.js

@@ -1,3 +1,5 @@
+var Migrations = artifacts.require("./Migrations.sol");
+
 module.exports = function(deployer) {
   deployer.deploy(Migrations);
 };

+ 3 - 7
migrations/2_deploy_contracts.js

@@ -1,9 +1,5 @@
+//var Ownable = artifacts.require("ownership/Ownable.sol");
+
 module.exports = function(deployer) {
-  deployer.deploy(Ownable);
-  deployer.deploy(Claimable);
-  deployer.deploy(LimitBalance);
-  if(deployer.network == 'test'){
-    deployer.deploy(SecureTargetBounty);
-    deployer.deploy(InsecureTargetBounty);
-  }
+  //deployer.deploy(Ownable);
 };

+ 3 - 2
package.json

@@ -7,11 +7,12 @@
     "babel-preset-es2015": "^6.18.0",
     "babel-preset-stage-2": "^6.18.0",
     "babel-preset-stage-3": "^6.17.0",
+    "babel-register": "^6.23.0",
     "ethereumjs-testrpc": "^3.0.2",
-    "truffle": "^2.1.1"
+    "truffle": "https://github.com/ConsenSys/truffle.git#3.1.9"
   },
   "scripts": {
-    "test": "truffle test",
+    "test": "scripts/test.sh",
     "console": "truffle console",
     "install": "scripts/install.sh"
   },

+ 13 - 0
scripts/test.sh

@@ -0,0 +1,13 @@
+#! /bin/bash
+
+output=$(nc -z localhost 8545; echo $?)
+[ $output -eq "0" ] && trpc_running=true
+if [ ! $trpc_running ]; then
+  echo "Starting our own testrpc node instance"
+  testrpc > /dev/null &
+  trpc_pid=$!
+fi
+./node_modules/truffle/cli.js test
+if [ ! $trpc_running ]; then
+  kill -9 $trpc_pid
+fi

+ 2 - 0
test/BasicToken.js

@@ -1,5 +1,7 @@
 const assertJump = require('./helpers/assertJump');
 
+var BasicTokenMock = artifacts.require("./helpers/BasicTokenMock.sol");
+
 contract('BasicToken', function(accounts) {
 
   it("should return the correct totalSupply after construction", async function() {

+ 51 - 52
test/Bounty.js

@@ -1,25 +1,39 @@
+'use strict';
+
 let sendReward = function(sender, receiver, value){
   web3.eth.sendTransaction({
     from:sender,
     to:receiver,
     value: value
-  })
+  });
+};
+var SecureTargetBounty = artifacts.require('helpers/SecureTargetBounty.sol');
+var InsecureTargetBounty = artifacts.require('helpers/InsecureTargetBounty.sol');
+
+function awaitEvent(event, handler) {
+  return new Promise((resolve, reject) => {
+    function wrappedHandler(...args) {
+      Promise.resolve(handler(...args)).then(resolve).catch(reject);
+    }
+  
+    event.watch(wrappedHandler);
+  });
 }
 
 contract('Bounty', function(accounts) {
 
-  it("sets reward", async function(){
+  it('sets reward', async function() {
     let owner = accounts[0];
-    let reward = web3.toWei(1, "ether");
+    let reward = web3.toWei(1, 'ether');
     let bounty = await SecureTargetBounty.new();
     sendReward(owner, bounty.address, reward);
 
     assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber());
-  })
+  });
 
-  it("empties itself when killed", async function(){
+  it('empties itself when killed', async function(){
     let owner = accounts[0];
-    let reward = web3.toWei(1, "ether");
+    let reward = web3.toWei(1, 'ether');
     let bounty = await SecureTargetBounty.new();
     sendReward(owner, bounty.address, reward);
 
@@ -27,89 +41,74 @@ contract('Bounty', function(accounts) {
 
     await bounty.kill();
     assert.equal(0, web3.eth.getBalance(bounty.address).toNumber());
-  })
-
-  describe("Against secure contract", function(){
+  });
 
-    it("checkInvariant returns true", async function(){
-      let bounty = await SecureTargetBounty.new();
-      let target = await bounty.createTarget();
-      let check = await bounty.checkInvariant.call();
+  describe('Against secure contract', function(){
 
-      assert.isTrue(check);
-    })
-
-    it("cannot claim reward", async function(done){
+    it('cannot claim reward', async function(){
       let owner = accounts[0];
       let researcher = accounts[1];
-      let reward = web3.toWei(1, "ether");
+      let reward = web3.toWei(1, 'ether');
       let bounty = await SecureTargetBounty.new();
       let event = bounty.TargetCreated({});
 
       event.watch(async function(err, result) {
         event.stopWatching();
-        if (err) { throw err }
+        if (err) { throw err; }
 
         var targetAddress = result.args.createdAddress;
         sendReward(owner, bounty.address, reward);
 
-        assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber())
+        assert.equal(reward,
+          web3.eth.getBalance(bounty.address).toNumber());
 
         try {
-          let tmpClain = await bounty.claim(targetAddress, {from:researcher});
-          done("should not come here");
+          await bounty.claim(targetAddress, {from:researcher});
+          assert.isTrue(false); // should never reach here
         } catch(error) {
             let reClaimedBounty = await bounty.claimed.call();
             assert.isFalse(reClaimedBounty);
 
-            try {
-              let withdraw = await bounty.withdrawPayments({from:researcher});
-              done("should not come here")
-            } catch (err) {
-              assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber());
-              done();
-            }
-        }//end of first try catch
+        }
+        try {
+          await bounty.withdrawPayments({from:researcher});
+          assert.isTrue(false); // should never reach here
+        } catch (err) {
+          assert.equal(reward,
+            web3.eth.getBalance(bounty.address).toNumber());
+        }
       });
       bounty.createTarget({from:researcher});
-    })
-  })
+    });
+  });
 
-  describe("Against broken contract", function(){
-    it("checkInvariant returns false", async function(){
-      let bounty = await InsecureTargetBounty.new();
-      let target = await bounty.createTarget();
-      let invariantCall = await bounty.checkInvariant.call();
-
-      assert.isFalse(invariantCall);
-    })
-
-    it("claims reward", async function(done){
+  describe('Against broken contract', function(){
+    it('claims reward', async function() {
       let owner = accounts[0];
       let researcher = accounts[1];
-      let reward = web3.toWei(1, "ether");
+      let reward = web3.toWei(1, 'ether');
       let bounty = await InsecureTargetBounty.new();
       let event = bounty.TargetCreated({});
-
-      event.watch(async function(err, result) {
+      
+      let watcher = async function(err, result) {
         event.stopWatching();
-        if (err) { throw err }
+        if (err) { throw err; }
         let targetAddress = result.args.createdAddress;
         sendReward(owner, bounty.address, reward);
 
         assert.equal(reward, web3.eth.getBalance(bounty.address).toNumber());
 
-        let bountyClaim = await bounty.claim(targetAddress, {from:researcher});
+        await bounty.claim(targetAddress, {from:researcher});
         let claim = await bounty.claimed.call();
 
         assert.isTrue(claim);
 
-        let payment = await bounty.withdrawPayments({from:researcher});
+        await bounty.withdrawPayments({from:researcher});
 
         assert.equal(0, web3.eth.getBalance(bounty.address).toNumber());
-        done();
-      })
+      };
       bounty.createTarget({from:researcher});
-    })
-  })
+      await awaitEvent(event, watcher);
+    });
+  });
 });

+ 16 - 12
test/Claimable.js

@@ -1,3 +1,7 @@
+'use strict';
+
+var Claimable = artifacts.require('../contracts/ownership/Claimable.sol');
+
 contract('Claimable', function(accounts) {
   let claimable;
 
@@ -5,34 +9,34 @@ contract('Claimable', function(accounts) {
     claimable = await Claimable.new();
   });
 
-  it("should have an owner", async function() {
+  it('should have an owner', async function() {
     let owner = await claimable.owner();
-    assert.isTrue(owner != 0);
+    assert.isTrue(owner !== 0);
   });
 
-  it("changes pendingOwner after transfer", async function() {
+  it('changes pendingOwner after transfer', async function() {
     let newOwner = accounts[1];
-    let transfer = await claimable.transferOwnership(newOwner);
+    await claimable.transferOwnership(newOwner);
     let pendingOwner = await claimable.pendingOwner();
 
     assert.isTrue(pendingOwner === newOwner);
   });
 
-  it("should prevent to claimOwnership from no pendingOwner", async function() {
-    let claimedOwner = await claimable.claimOwnership({from: accounts[2]});
+  it('should prevent to claimOwnership from no pendingOwner', async function() {
+    claimable.claimOwnership({from: accounts[2]});
     let owner = await claimable.owner();
 
-    assert.isTrue(owner != accounts[2]);
+    assert.isTrue(owner !== accounts[2]);
   });
 
-  it("should prevent non-owners from transfering", async function() {
-    let transfer = await claimable.transferOwnership(accounts[2], {from: accounts[2]});
+  it('should prevent non-owners from transfering', async function() {
+    await claimable.transferOwnership(accounts[2], {from: accounts[2]});
     let pendingOwner = await claimable.pendingOwner();
 
     assert.isFalse(pendingOwner === accounts[2]);
   });
 
-  describe("after initiating a transfer", function () {
+  describe('after initiating a transfer', function () {
     let newOwner;
 
     beforeEach(async function () {
@@ -40,8 +44,8 @@ contract('Claimable', function(accounts) {
       await claimable.transferOwnership(newOwner);
     });
 
-    it("changes allow pending owner to claim ownership", async function() {
-      let claimedOwner = await claimable.claimOwnership({from: newOwner})
+    it('changes allow pending owner to claim ownership', async function() {
+      await claimable.claimOwnership({from: newOwner});
       let owner = await claimable.owner();
 
       assert.isTrue(owner === newOwner);

+ 4 - 0
test/DayLimit.js

@@ -1,3 +1,7 @@
+'use strict';
+
+var DayLimitMock = artifacts.require('helpers/DayLimitMock.sol');
+
 contract('DayLimit', function(accounts) {
 
   it('should construct with the passed daily limit', async function() {

+ 52 - 66
test/DelayedClaimble.js

@@ -1,3 +1,7 @@
+'use strict';
+
+var DelayedClaimable = artifacts.require('../contracts/ownership/DelayedClaimable.sol');
+
 contract('DelayedClaimable', function(accounts) {
   var delayedClaimable;
 
@@ -7,76 +11,58 @@ contract('DelayedClaimable', function(accounts) {
     });
   });
 
-  it("Changes pendingOwner after transfer succesfull", function(done) {
-    return delayedClaimable.transferOwnership(accounts[2])
-      .then(function(){
-        return delayedClaimable.setClaimBlocks(1000,0);
-      })
-      .then(function(){
-        return delayedClaimable.claimBeforeBlock();
-      })
-      .then(function(claimBeforeBlock) {
-        assert.isTrue(claimBeforeBlock == 1000);
-        return delayedClaimable.claimAfterBlock();
-      })
-      .then(function(claimAfterBlock) {
-        assert.isTrue(claimAfterBlock == 0);
-        return delayedClaimable.pendingOwner();
-      })
-      .then(function(pendingOwner) {
-        assert.isTrue(pendingOwner === accounts[2]);
-        return delayedClaimable.claimOwnership({from: accounts[2]});
-      })
-      .then(function() {
-        return delayedClaimable.owner();
-      })
-      .then(function(owner) {
-        assert.isTrue(owner === accounts[2]);
-      })
-      .then(done);
+  it('can set claim blocks', async function() {
+    await delayedClaimable.transferOwnership(accounts[2]);
+    await delayedClaimable.setLimits(0, 1000);
+    let end = await delayedClaimable.end();
+    assert.equal(end, 1000);
+    let start = await delayedClaimable.start();
+    assert.equal(start, 0);
+  });
+
+  it('changes pendingOwner after transfer successful', async function() {
+    await delayedClaimable.transferOwnership(accounts[2]);
+    await delayedClaimable.setLimits(0, 1000);
+    let end = await delayedClaimable.end();
+    assert.equal(end, 1000);
+    let start = await delayedClaimable.start();
+    assert.equal(start, 0);
+    let pendingOwner = await delayedClaimable.pendingOwner();
+    assert.equal(pendingOwner, accounts[2]);
+    await delayedClaimable.claimOwnership({from: accounts[2]});
+    let owner = await delayedClaimable.owner();
+    assert.equal(owner, accounts[2]);
   });
 
-  it("Changes pendingOwner after transfer fails", function(done) {
-    return delayedClaimable.transferOwnership(accounts[1])
-      .then(function(){
-        return delayedClaimable.setClaimBlocks(11000,10000);
-      })
-      .then(function(){
-        return delayedClaimable.claimBeforeBlock();
-      })
-      .then(function(claimBeforeBlock) {
-        assert.isTrue(claimBeforeBlock == 11000);
-        return delayedClaimable.claimAfterBlock();
-      })
-      .then(function(claimAfterBlock) {
-        assert.isTrue(claimAfterBlock == 10000);
-        return delayedClaimable.pendingOwner();
-      })
-      .then(function(pendingOwner) {
-        assert.isTrue(pendingOwner === accounts[1]);
-        return delayedClaimable.claimOwnership({from: accounts[1]});
-      })
-      .catch(function(error) {
-        if (error.message.search('invalid JUMP') == -1) throw error;
-      })
-      .then(function() {
-        return delayedClaimable.owner();
-      })
-      .then(function(owner) {
-        assert.isTrue(owner != accounts[1]);
-      })
-      .then(done);
+  it('changes pendingOwner after transfer fails', async function() {
+    await delayedClaimable.transferOwnership(accounts[1]);
+    await delayedClaimable.setLimits(100, 110);
+    let end = await delayedClaimable.end();
+    assert.equal(end, 110);
+    let start = await delayedClaimable.start();
+    assert.equal(start, 100);
+    let pendingOwner = await delayedClaimable.pendingOwner();
+    assert.equal(pendingOwner, accounts[1]);
+    var err = null;
+    try {
+      await delayedClaimable.claimOwnership({from: accounts[1]});
+    } catch (error) {
+      err = error;
+    }
+    assert.isFalse(err.message.search('invalid JUMP') === -1);
+    let owner = await delayedClaimable.owner();
+    assert.isTrue(owner !== accounts[1]);
   });
 
-  it("Set claimBeforeBlock and claimAfterBlock invalid values fail", function(done) {
-    return delayedClaimable.transferOwnership(accounts[1])
-      .then(function(){
-        return delayedClaimable.setClaimBlocks(1000,10000);
-      })
-      .catch(function(error) {
-        if (error.message.search('invalid JUMP') == -1) throw error;
-      })
-      .then(done);
+  it('set end and start invalid values fail', async function() {
+    await delayedClaimable.transferOwnership(accounts[1]);
+    var err = null;
+    try {
+      await delayedClaimable.setLimits(1001, 1000);
+    } catch (error) {
+      err = error;
+    }
+    assert.isFalse(err.message.search('invalid JUMP') === -1);
   });
 
 });

+ 10 - 45
test/Killable.js

@@ -1,51 +1,16 @@
+'use strict';
 
-contract('Killable', function(accounts) {
-  //from https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6
-  web3.eth.getTransactionReceiptMined = function (txnHash, interval) {
-    var transactionReceiptAsync;
-    interval = interval ? interval : 500;
-    transactionReceiptAsync = function(txnHash, resolve, reject) {
-        try {
-            var receipt = web3.eth.getTransactionReceipt(txnHash);
-            if (receipt === null) {
-                setTimeout(function () {
-                    transactionReceiptAsync(txnHash, resolve, reject);
-                }, interval);
-            } else {
-                resolve(receipt);
-            }
-        } catch(e) {
-            reject(e);
-        }
-    };
-
-    if (Array.isArray(txnHash)) {
-        var promises = [];
-        txnHash.forEach(function (oneTxHash) {
-            promises.push(web3.eth.getTransactionReceiptMined(oneTxHash, interval));
-        });
-        return Promise.all(promises);
-    } else {
-        return new Promise(function (resolve, reject) {
-                transactionReceiptAsync(txnHash, resolve, reject);
-            });
-    }
-};
+var Killable = artifacts.require('../contracts/lifecycle/Killable.sol');
+require('./helpers/transactionMined.js');
 
-  it("should send balance to owner after death", async function() {
-    let initBalance, newBalance, owner, address, killable, kBalance, txnHash, receiptMined;
-    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('50','ether')}, function(err, result) {
-      if(err)
-        console.log("ERROR:" + err);
-    });
+contract('Killable', function(accounts) {
 
-    killable = await Killable.new({from: accounts[0], value: web3.toWei('10','ether')});
-    owner = await killable.owner();
-    initBalance = web3.eth.getBalance(owner);
-    kBalance = web3.eth.getBalance(killable.address);
-    txnHash = await killable.kill({from: owner});
-    receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
-    newBalance = web3.eth.getBalance(owner);
+  it('should send balance to owner after death', async function() {
+    let killable = await Killable.new({from: accounts[0], value: web3.toWei('10','ether')});
+    let owner = await killable.owner();
+    let initBalance = web3.eth.getBalance(owner);
+    await killable.kill({from: owner});
+    let newBalance = web3.eth.getBalance(owner);
 
     assert.isTrue(newBalance > initBalance);
   });

+ 14 - 11
test/LimitBalance.js

@@ -1,3 +1,6 @@
+'use strict';
+
+var LimitBalanceMock = artifacts.require('helpers/LimitBalanceMock.sol');
 const assertJump = require('./helpers/assertJump');
 
 contract('LimitBalance', function(accounts) {
@@ -9,46 +12,46 @@ contract('LimitBalance', function(accounts) {
 
   let LIMIT = 1000;
 
-  it("should expose limit", async function() {
+  it('should expose limit', async function() {
     let limit = await lb.limit();
     assert.equal(limit, LIMIT);
   });
 
-  it("should allow sending below limit", async function() {
+  it('should allow sending below limit', async function() {
     let amount = 1;
-    let limDeposit = await lb.limitedDeposit({value: amount});
+    await lb.limitedDeposit({value: amount});
 
     assert.equal(web3.eth.getBalance(lb.address), amount);
   });
 
-  it("shouldnt allow sending above limit", async function() {
+  it('shouldnt allow sending above limit', async function() {
     let amount = 1110;
     try {
-      let limDeposit = await lb.limitedDeposit({value: amount});
+       await lb.limitedDeposit({value: amount});
     } catch(error) {
       return assertJump(error);
     }
     assert.fail('should have thrown before');
   });
 
-  it("should allow multiple sends below limit", async function() {
+  it('should allow multiple sends below limit', async function() {
     let amount = 500;
-    let limDeposit = await lb.limitedDeposit({value: amount});
+    await lb.limitedDeposit({value: amount});
 
     assert.equal(web3.eth.getBalance(lb.address), amount);
 
-    let limDeposit2 = await lb.limitedDeposit({value: amount});
+    await lb.limitedDeposit({value: amount});
     assert.equal(web3.eth.getBalance(lb.address), amount*2);
   });
 
-  it("shouldnt allow multiple sends above limit", async function() {
+  it('shouldnt allow multiple sends above limit', async function() {
     let amount = 500;
-    let limDeposit = await lb.limitedDeposit({value: amount});
+    await lb.limitedDeposit({value: amount});
 
     assert.equal(web3.eth.getBalance(lb.address), amount);
 
     try {
-      await lb.limitedDeposit({value: amount+1})
+      await lb.limitedDeposit({value: amount+1});
     } catch(error) {
       return assertJump(error);
     }

+ 11 - 55
test/MultisigWallet.js

@@ -1,43 +1,15 @@
-contract('MultisigWallet', function(accounts) {
-  //from https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6
-  web3.eth.getTransactionReceiptMined = function (txnHash, interval) {
-    var transactionReceiptAsync;
-    interval = interval ? interval : 500;
-    transactionReceiptAsync = function(txnHash, resolve, reject) {
-        try {
-            var receipt = web3.eth.getTransactionReceipt(txnHash);
-            if (receipt == null) {
-                setTimeout(function () {
-                    transactionReceiptAsync(txnHash, resolve, reject);
-                }, interval);
-            } else {
-                resolve(receipt);
-            }
-        } catch(e) {
-            reject(e);
-        }
-    };
-
-    if (Array.isArray(txnHash)) {
-        var promises = [];
-        txnHash.forEach(function (oneTxHash) {
-            promises.push(web3.eth.getTransactionReceiptMined(oneTxHash, interval));
-        });
-        return Promise.all(promises);
-    } else {
-        return new Promise(function (resolve, reject) {
-                transactionReceiptAsync(txnHash, resolve, reject);
-            });
-    }
-};
+'use strict';
 
+var MultisigWalletMock = artifacts.require('./helpers/MultisigWalletMock.sol');
+require('./helpers/transactionMined.js');
 
+contract('MultisigWallet', function(accounts) {
+  let shouldntFail = function(err) {
+    assert.isFalse(!!err);
+  };
   it('should send balance to passed address upon death', async function() {
     //Give account[0] 20 ether
-    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, function(err, result) {
-      if(err)
-        console.log("ERROR:" + err);
-    });
+    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, shouldntFail);
 
     let dailyLimit = 10;
     let ownersRequired = 2;
@@ -54,8 +26,6 @@ contract('MultisigWallet', function(accounts) {
     await wallet.kill(accounts[0], {data: hash});
     let txnHash = await wallet.kill(accounts[0], {from: accounts[1], data: hash});
 
-    let receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
-
     //Get balances of owner and wallet after kill function is complete, compare with previous values
     let newOwnerBalance = web3.eth.getBalance(accounts[0]);
     let newWalletBalance = web3.eth.getBalance(wallet.address);
@@ -66,10 +36,7 @@ contract('MultisigWallet', function(accounts) {
 
   it('should execute transaction if below daily limit', async function() {
     //Give account[0] 20 ether
-    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, function(err, result) {
-      if(err)
-        console.log("ERROR:" + err);
-    });
+    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, shouldntFail);
 
     let dailyLimit = 10;
     let ownersRequired = 2;
@@ -82,7 +49,6 @@ contract('MultisigWallet', function(accounts) {
 
     //Owner account0 commands wallet to send 9 wei to account2
     let txnHash = await wallet.execute(accounts[2], 9, hash);
-    let receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
 
     //Balance of account2 should have increased
     let newAccountBalance = web3.eth.getBalance(accounts[2]);
@@ -91,10 +57,7 @@ contract('MultisigWallet', function(accounts) {
 
   it('should prevent execution of transaction if above daily limit', async function() {
     //Give account[0] 20 ether
-    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, function(err, result) {
-      if(err)
-        console.log("ERROR:" + err);
-    });
+    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, shouldntFail);
 
     let dailyLimit = 10;
     let ownersRequired = 2;
@@ -107,7 +70,6 @@ contract('MultisigWallet', function(accounts) {
 
     //Owner account0 commands wallet to send 9 wei to account2
     let txnHash = await wallet.execute(accounts[2], 9, hash);
-    let receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
 
     //Balance of account2 should have increased
     let newAccountBalance = web3.eth.getBalance(accounts[2]);
@@ -118,7 +80,6 @@ contract('MultisigWallet', function(accounts) {
 
     //Owner account0 commands wallet to send 2 more wei to account2, going over the daily limit of 10
     txnHash = await wallet.execute(accounts[2], 2, hash);
-    receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
 
     //Balance of account2 should not change
     newAccountBalance = web3.eth.getBalance(accounts[2]);
@@ -127,10 +88,7 @@ contract('MultisigWallet', function(accounts) {
 
   it('should execute transaction if above daily limit and enough owners approve', async function() {
     //Give account[0] 20 ether
-    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, function(err, result) {
-      if(err)
-        console.log("ERROR:" + err);
-    });
+    web3.eth.sendTransaction({from: web3.eth.coinbase, to: accounts[0], value: web3.toWei('20','ether')}, shouldntFail);
 
     let dailyLimit = 10;
     let ownersRequired = 2;
@@ -143,7 +101,6 @@ contract('MultisigWallet', function(accounts) {
 
     //Owner account0 commands wallet to send 11 wei to account2
     let txnHash = await wallet.execute(accounts[2], 11, hash);
-    let receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
 
     //Balance of account2 should not change
     let newAccountBalance = web3.eth.getBalance(accounts[2]);
@@ -153,7 +110,6 @@ contract('MultisigWallet', function(accounts) {
 
     //Owner account1 commands wallet to send 11 wei to account2
     txnHash = await wallet.execute(accounts[2], 2, hash);
-    receiptMined = await web3.eth.getTransactionReceiptMined(txnHash);
 
     //Balance of account2 should change
     newAccountBalance = web3.eth.getBalance(accounts[2]);

+ 12 - 9
test/Ownable.js

@@ -1,3 +1,7 @@
+'use strict';
+
+var Ownable = artifacts.require('../contracts/ownership/Ownable.sol');
+
 contract('Ownable', function(accounts) {
   let ownable;
 
@@ -5,31 +9,30 @@ contract('Ownable', function(accounts) {
     ownable = await Ownable.new();
   });
 
-  it("should have an owner", async function() {
+  it('should have an owner', async function() {
     let owner = await ownable.owner();
-    assert.isTrue(owner != 0);
+    assert.isTrue(owner !== 0);
   });
 
-  it("changes owner after transfer", async function() {
+  it('changes owner after transfer', async function() {
     let other = accounts[1];
-    let transfer = await ownable.transferOwnership(other);
+    await ownable.transferOwnership(other);
     let owner = await ownable.owner();
 
     assert.isTrue(owner === other);
   });
 
-  it("should prevent non-owners from transfering", async function() {
+  it('should prevent non-owners from transfering', async function() {
     let other = accounts[2];
-    let transfer = await ownable.transferOwnership(other, {from: accounts[2]});
+    await ownable.transferOwnership(other, {from: accounts[2]});
     let owner = await ownable.owner();
 
      assert.isFalse(owner === other);
   });
 
-  it("should guard ownership against stuck state", async function() {
-    let ownable = Ownable.deployed();
+  it('should guard ownership against stuck state', async function() {
     let originalOwner = await ownable.owner();
-    let transfer = await ownable.transferOwnership(null, {from: originalOwner});
+    await ownable.transferOwnership(null, {from: originalOwner});
     let newOwner = await ownable.owner();
 
     assert.equal(originalOwner, newOwner);

+ 18 - 14
test/Pausable.js

@@ -1,49 +1,53 @@
+'use strict';
+
+var PausableMock = artifacts.require('helpers/PausableMock.sol');
+
 contract('Pausable', function(accounts) {
 
-  it("can perform normal process in non-emergency", async function() {
+  it('can perform normal process in non-emergency', async function() {
     let Pausable = await PausableMock.new();
     let count0 = await Pausable.count();
     assert.equal(count0, 0);
 
-    let normalProcess = await Pausable.normalProcess();
+    await Pausable.normalProcess();
     let count1 = await Pausable.count();
     assert.equal(count1, 1);
   });
 
-  it("can not perform normal process in emergency", async function() {
+  it('can not perform normal process in emergency', async function() {
     let Pausable = await PausableMock.new();
-    let emergencyStop = await Pausable.emergencyStop();
+    await Pausable.emergencyStop();
     let count0 = await Pausable.count();
     assert.equal(count0, 0);
 
-    let normalProcess = await Pausable.normalProcess();
+    await Pausable.normalProcess();
     let count1 = await Pausable.count();
     assert.equal(count1, 0);
   });
 
 
-  it("can not take drastic measure in non-emergency", async function() {
+  it('can not take drastic measure in non-emergency', async function() {
     let Pausable = await PausableMock.new();
-    let drasticMeasure = await Pausable.drasticMeasure();
+    await Pausable.drasticMeasure();
     let drasticMeasureTaken = await Pausable.drasticMeasureTaken();
 
     assert.isFalse(drasticMeasureTaken);
   });
 
-  it("can take a drastic measure in an emergency", async function() {
+  it('can take a drastic measure in an emergency', async function() {
     let Pausable = await PausableMock.new();
-    let emergencyStop = await Pausable.emergencyStop();
-    let drasticMeasure = await Pausable.drasticMeasure();
+    await Pausable.emergencyStop();
+    await Pausable.drasticMeasure();
     let drasticMeasureTaken = await Pausable.drasticMeasureTaken();
 
     assert.isTrue(drasticMeasureTaken);
   });
 
-  it("should resume allowing normal process after emergency is over", async function() {
+  it('should resume allowing normal process after emergency is over', async function() {
     let Pausable = await PausableMock.new();
-    let emergencyStop = await Pausable.emergencyStop();
-    let release = await Pausable.release();
-    let normalProcess = await Pausable.normalProcess();
+    await Pausable.emergencyStop();
+    await Pausable.release();
+    await Pausable.normalProcess();
     let count0 = await Pausable.count();
 
     assert.equal(count0, 1);

+ 2 - 0
test/PullPayment.js

@@ -1,3 +1,5 @@
+var PullPaymentMock = artifacts.require("./helpers/PullPaymentMock.sol");
+
 contract('PullPayment', function(accounts) {
 
   it("can't call asyncSend externally", async function() {

+ 1 - 0
test/SafeMath.js

@@ -1,4 +1,5 @@
 const assertJump = require('./helpers/assertJump');
+var SafeMathMock = artifacts.require("./helpers/SafeMathMock.sol");
 
 contract('SafeMath', function(accounts) {
 

+ 2 - 0
test/Shareable.js

@@ -1,3 +1,5 @@
+var ShareableMock = artifacts.require("./helpers/ShareableMock.sol");
+
 contract('Shareable', function(accounts) {
 
   it('should construct with correct owners and number of sigs required', async function() {

+ 1 - 0
test/StandardToken.js

@@ -1,4 +1,5 @@
 const assertJump = require('./helpers/assertJump');
+var StandardTokenMock = artifacts.require("./helpers/StandardTokenMock.sol");
 
 contract('StandardToken', function(accounts) {
 

+ 1 - 0
test/VestedToken.js

@@ -1,5 +1,6 @@
 const assertJump = require('./helpers/assertJump');
 const timer = require('./helpers/timer');
+var VestedTokenMock = artifacts.require("./helpers/VestedTokenMock.sol");
 
 contract('VestedToken', function(accounts) {
   let token = null

+ 1 - 1
contracts/test-helpers/BasicTokenMock.sol → test/helpers/BasicTokenMock.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import '../token/BasicToken.sol';
+import '../../contracts/token/BasicToken.sol';
 
 
 // mock class using BasicToken

+ 1 - 1
contracts/test-helpers/DayLimitMock.sol → test/helpers/DayLimitMock.sol

@@ -1,5 +1,5 @@
 pragma solidity ^0.4.4;
-import "../DayLimit.sol";
+import "../../contracts/DayLimit.sol";
 
 contract DayLimitMock is DayLimit {
   uint public totalSpending;

+ 1 - 1
contracts/test-helpers/InsecureTargetBounty.sol → test/helpers/InsecureTargetBounty.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import {Bounty, Target} from "../Bounty.sol";
+import {Bounty, Target} from "../../contracts/Bounty.sol";
 
 
 contract InsecureTargetMock is Target {

+ 1 - 1
contracts/test-helpers/LimitBalanceMock.sol → test/helpers/LimitBalanceMock.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import '../LimitBalance.sol';
+import '../../contracts/LimitBalance.sol';
 
 
 // mock class using LimitBalance

+ 1 - 1
contracts/test-helpers/MultisigWalletMock.sol → test/helpers/MultisigWalletMock.sol

@@ -1,5 +1,5 @@
 pragma solidity ^0.4.4;
-import "../MultisigWallet.sol";
+import "../../contracts/MultisigWallet.sol";
 
 contract MultisigWalletMock is MultisigWallet {
   uint public totalSpending;

+ 1 - 1
contracts/test-helpers/PausableMock.sol → test/helpers/PausableMock.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import '../lifecycle/Pausable.sol';
+import '../../contracts/lifecycle/Pausable.sol';
 
 
 // mock class using Pausable

+ 1 - 1
contracts/test-helpers/PullPaymentMock.sol → test/helpers/PullPaymentMock.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import '../payment/PullPayment.sol';
+import '../../contracts/payment/PullPayment.sol';
 
 
 // mock class using PullPayment

+ 1 - 1
contracts/test-helpers/SafeMathMock.sol → test/helpers/SafeMathMock.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import '../SafeMath.sol';
+import '../../contracts/SafeMath.sol';
 
 
 contract SafeMathMock is SafeMath {

+ 1 - 1
contracts/test-helpers/SecureTargetBounty.sol → test/helpers/SecureTargetBounty.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import {Bounty, Target} from "../Bounty.sol";
+import {Bounty, Target} from "../../contracts/Bounty.sol";
 
 
 contract SecureTargetMock is Target {

+ 1 - 1
contracts/test-helpers/ShareableMock.sol → test/helpers/ShareableMock.sol

@@ -1,5 +1,5 @@
 pragma solidity ^0.4.4;
-import "../ownership/Shareable.sol";
+import "../../contracts/ownership/Shareable.sol";
 
 contract ShareableMock is Shareable {
 

+ 1 - 1
contracts/test-helpers/StandardTokenMock.sol → test/helpers/StandardTokenMock.sol

@@ -1,7 +1,7 @@
 pragma solidity ^0.4.4;
 
 
-import '../token/StandardToken.sol';
+import '../../contracts/token/StandardToken.sol';
 
 
 // mock class using StandardToken

+ 1 - 1
contracts/test-helpers/VestedTokenMock.sol → test/helpers/VestedTokenMock.sol

@@ -1,6 +1,6 @@
 pragma solidity ^0.4.4;
 
-import '../token/VestedToken.sol';
+import '../../contracts/token/VestedToken.sol';
 
 // mock class using StandardToken
 contract VestedTokenMock is VestedToken {

+ 34 - 0
test/helpers/transactionMined.js

@@ -0,0 +1,34 @@
+'use strict';
+
+//from https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6
+module.export = web3.eth.transactionMined = function (txnHash, interval) {
+  var transactionReceiptAsync;
+  interval = interval ? interval : 500;
+  transactionReceiptAsync = function(txnHash, resolve, reject) {
+    try {
+      var receipt = web3.eth.getTransactionReceipt(txnHash);
+      if (receipt === null) {
+        setTimeout(function () {
+          transactionReceiptAsync(txnHash, resolve, reject);
+        }, interval);
+      } else {
+        resolve(receipt);
+      }
+    } catch(e) {
+      reject(e);
+    }
+  };
+
+  if (Array.isArray(txnHash)) {
+    var promises = [];
+    txnHash.forEach(function (oneTxHash) {
+      promises.push(
+        web3.eth.getTransactionReceiptMined(oneTxHash, interval));
+    });
+    return Promise.all(promises);
+  } else {
+    return new Promise(function (resolve, reject) {
+      transactionReceiptAsync(txnHash, resolve, reject);
+    });
+  }
+};

+ 9 - 3
truffle.js

@@ -1,6 +1,12 @@
+require('babel-register');
+require('babel-polyfill');
+
 module.exports = {
-  rpc: {
-    host: "localhost",
-    port: 8545
+  networks: {
+    development: {
+      host: "localhost",
+      port: 8545,
+      network_id: "*"
+    }
   }
 };